<?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: Gleanery Works</title>
    <description>The latest articles on DEV Community by Gleanery Works (@gleaneryworks).</description>
    <link>https://dev.to/gleaneryworks</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%2F4196175%2F222f1893-118d-494a-b22f-c03848ee8bad.png</url>
      <title>DEV Community: Gleanery Works</title>
      <link>https://dev.to/gleaneryworks</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/gleaneryworks"/>
    <language>en</language>
    <item>
      <title>Finding European manufacturers with VAT IDs: a sourcing workflow with Europages data</title>
      <dc:creator>Gleanery Works</dc:creator>
      <pubDate>Fri, 23 Oct 2026 07:49:28 +0000</pubDate>
      <link>https://dev.to/gleaneryworks/finding-european-manufacturers-with-vat-ids-a-sourcing-workflow-with-europages-data-4946</link>
      <guid>https://dev.to/gleaneryworks/finding-european-manufacturers-with-vat-ids-a-sourcing-workflow-with-europages-data-4946</guid>
      <description>&lt;p&gt;When you need a manufacturer in Europe (a private-label cosmetics lab, a CNC machining subcontractor in Poland, an olive-oil producer in Spain), you usually start on &lt;strong&gt;Europages&lt;/strong&gt;. It lists over 3 million companies, and they fill in their own profiles: products, employee count, founding year, sales area, and often their &lt;strong&gt;VAT number, payment terms and incoterms&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The problem is the interface. You click through 30 results per page, open each profile, and copy fields into a spreadsheet by hand.&lt;/p&gt;

&lt;h2&gt;
  
  
  A faster workflow
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Search wide.&lt;/strong&gt; Product keyword plus countries, e.g. &lt;code&gt;cnc machining&lt;/code&gt; in Poland, Czechia, Slovakia and Hungary. Europages caps each search at 3,000 results, so split big searches by country.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Filter hard.&lt;/strong&gt; Keep only &lt;strong&gt;manufacturers&lt;/strong&gt; (not distributors), with &lt;strong&gt;20–199 employees&lt;/strong&gt;, an &lt;strong&gt;international&lt;/strong&gt; sales area and a &lt;strong&gt;website&lt;/strong&gt;. That usually cuts the list by 80%.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Enrich the shortlist.&lt;/strong&gt; Pull the VAT ID, main industry, payment methods and terms, incoterms, certificates and product keywords from each profile.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Verify the VAT ID&lt;/strong&gt; in the EU's &lt;a href="https://ec.europa.eu/taxation_customs/vies/" rel="noopener noreferrer"&gt;VIES&lt;/a&gt; service. It's a quick check that the company is a real, registered business.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Compare and contact.&lt;/strong&gt; Sort by size, founding year and trade terms, then contact the top 10 through their website.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  What the data looks like
&lt;/h2&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="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"companyName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"SOGA Spaces Office Furniture"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"country"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"TR"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"city"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Istanbul"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"website"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://www.sogaspaces.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"phone"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"+905336997642"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"employeeCount"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"20-49"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"supplierTypes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"production"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"distributionArea"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"international"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"industry"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Furniture and contract furnishing"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"vatId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"TR7721315900"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"paymentTerms"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"payment_on_account"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"incoterms"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"cost_insurance_and_freight"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"free_on_board"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"keywords"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Acoustic panels"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Office desks"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Meeting tables"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  A note on GDPR
&lt;/h2&gt;

&lt;p&gt;Company data (name, website, switchboard phone, VAT ID) is business information that companies publish so buyers can find them. Named contact persons are personal data. Leave them out, and follow your country's ePrivacy rules before cold-emailing anyone.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tooling
&lt;/h2&gt;

&lt;p&gt;I built &lt;a href="https://apify.com/gleanery_actors/europages-scraper" rel="noopener noreferrer"&gt;Europages Scraper&lt;/a&gt; for steps 1–3. It covers keyword plus country search with automatic splitting past the 3,000 limit, filters for supplier type, size, sales area and founding year, and VAT/trade-terms enrichment. It deliberately leaves out personal data. It costs $1 per 1,000 companies, all-in.&lt;/p&gt;

&lt;p&gt;Ready-made searches you can copy:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://apify.com/gleanery_actors/europages-scraper/examples/cosmetics-private-label-manufacturers" rel="noopener noreferrer"&gt;Private-label cosmetics manufacturers in Europe&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://apify.com/gleanery_actors/europages-scraper/examples/cnc-machining-suppliers" rel="noopener noreferrer"&gt;CNC machining suppliers in Central Europe&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://apify.com/gleanery_actors/europages-scraper/examples/textile-manufacturers-portugal-turkey" rel="noopener noreferrer"&gt;Textile manufacturers in Portugal and Turkey&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://apify.com/gleanery_actors/europages-scraper/examples/furniture-manufacturers-poland" rel="noopener noreferrer"&gt;Furniture manufacturers in Poland&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Let an AI agent do the sourcing:&lt;/strong&gt; add &lt;code&gt;https://mcp.apify.com?tools=gleanery_actors/europages-scraper&lt;/code&gt; as an MCP server in Claude, Cursor or ChatGPT, and ask &lt;em&gt;"Find 30 private-label cosmetics manufacturers in Italy and France with more than 20 employees, with VAT IDs, and rank them by size."&lt;/em&gt; (&lt;a href="https://apify.com/gleanery_actors/europages-scraper" rel="noopener noreferrer"&gt;setup guide&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;What are you sourcing? Tell me in the comments and I'll suggest a search.&lt;/p&gt;

</description>
      <category>ecommerce</category>
      <category>b2b</category>
      <category>data</category>
      <category>sourcing</category>
    </item>
    <item>
      <title>Startup salaries and equity, as data: exporting Wellfound (AngelList) jobs</title>
      <dc:creator>Gleanery Works</dc:creator>
      <pubDate>Thu, 22 Oct 2026 07:57:11 +0000</pubDate>
      <link>https://dev.to/gleaneryworks/startup-salaries-and-equity-as-data-exporting-wellfound-angellist-jobs-8f5</link>
      <guid>https://dev.to/gleaneryworks/startup-salaries-and-equity-as-data-exporting-wellfound-angellist-jobs-8f5</guid>
      <description>&lt;p&gt;Wellfound (formerly AngelList Talent) is unusual among job boards: most listings show &lt;strong&gt;both a salary range and an equity range&lt;/strong&gt;, plus the company's funding stage, size and investor badges. That makes it the best public dataset on startup compensation, if you can get it out of the website.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where the data lives
&lt;/h2&gt;

&lt;p&gt;Wellfound is a Next.js app. Each search page (&lt;code&gt;/role/software-engineer&lt;/code&gt;, &lt;code&gt;/location/berlin&lt;/code&gt;, &lt;code&gt;/remote&lt;/code&gt;) ships its data in a &lt;code&gt;&amp;lt;script id="__NEXT_DATA__"&amp;gt;&lt;/code&gt; tag as an Apollo cache. The useful records are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;JobListingSearchResult&lt;/code&gt;: title, &lt;code&gt;compensation&lt;/code&gt; (a display string like &lt;code&gt;$120k – $160k • 0.1% – 0.5%&lt;/code&gt;), &lt;code&gt;jobType&lt;/code&gt;, &lt;code&gt;remote&lt;/code&gt;, &lt;code&gt;locationNames&lt;/code&gt;, &lt;code&gt;yearsExperienceMin&lt;/code&gt;, &lt;code&gt;liveStartAt&lt;/code&gt;, and a reference to the startup.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;StartupResult&lt;/code&gt;: name, &lt;code&gt;companySize&lt;/code&gt;, &lt;code&gt;highConcept&lt;/code&gt; (one-liner), and &lt;code&gt;badges[]&lt;/code&gt; such as &lt;em&gt;Actively hiring&lt;/em&gt;, &lt;em&gt;Top investors&lt;/em&gt;, &lt;em&gt;B2B&lt;/em&gt; and the funding stage.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The job detail page adds a schema.org &lt;code&gt;JobPosting&lt;/code&gt; block in &lt;code&gt;ld+json&lt;/code&gt;. It has the company website, industry, benefits, &lt;code&gt;directApply&lt;/code&gt;, applicant location requirements and a structured &lt;code&gt;baseSalary&lt;/code&gt; with its unit (year/month/hour).&lt;/p&gt;

&lt;h2&gt;
  
  
  The annoying parts
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Compensation is a string.&lt;/strong&gt; You need to parse &lt;code&gt;$120k – $160k&lt;/code&gt;, &lt;code&gt;€50K – €70K&lt;/code&gt;, &lt;code&gt;₹15L – ₹25L&lt;/code&gt; and &lt;code&gt;0.1% – 1.0%&lt;/code&gt; into min/max numbers and currencies. Watch out for &lt;code&gt;k&lt;/code&gt;, &lt;code&gt;m&lt;/code&gt; and Indian lakh (&lt;code&gt;L&lt;/code&gt;) multipliers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pagination stops around page 46&lt;/strong&gt;, so a broad query like "software engineer" doesn't return everything. Split by role and location.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Detail pages cost requests.&lt;/strong&gt; You only need them for the website, industry and salary period, so fetch them in parallel with a small concurrency limit.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Daily feeds.&lt;/strong&gt; If you run this every morning, you want only new jobs. Keep a hash of each job's key fields between runs.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  What you can do with it
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Comp benchmarking:&lt;/strong&gt; median salary and equity for a senior engineer at a seed-stage vs. Series B company.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Job hunting at scale:&lt;/strong&gt; filter all remote jobs by minimum salary, then sort by equity.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lead lists:&lt;/strong&gt; seed-stage startups that are actively hiring are startups that just raised money. Recruiters, agencies and dev shops sell to them.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Job boards and newsletters:&lt;/strong&gt; a daily feed of new remote startup jobs.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The shortcut
&lt;/h2&gt;

&lt;p&gt;I packaged all of the above as &lt;a href="https://apify.com/gleanery_actors/wellfound-jobs-scraper" rel="noopener noreferrer"&gt;Wellfound Jobs Scraper&lt;/a&gt; on Apify. It returns salary and equity as numbers, plus company website, industry, stage, size, investor badges and remote policy. It has filters (minimum salary, equity only, company stage, years of experience) and a "new jobs only" mode for daily schedules. Pricing is pay per result, $0.90 per 1,000 jobs.&lt;/p&gt;

&lt;p&gt;Some ready-made searches:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://apify.com/gleanery_actors/wellfound-jobs-scraper/examples/startup-jobs-with-salary-and-equity" rel="noopener noreferrer"&gt;Startup jobs with salary and equity ranges&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://apify.com/gleanery_actors/wellfound-jobs-scraper/examples/high-paying-startup-jobs" rel="noopener noreferrer"&gt;High-paying startup jobs ($150k+)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://apify.com/gleanery_actors/wellfound-jobs-scraper/examples/seed-stage-startups-hiring" rel="noopener noreferrer"&gt;Seed-stage startups that are hiring&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;From an AI agent:&lt;/strong&gt; add &lt;code&gt;https://mcp.apify.com?tools=gleanery_actors/wellfound-jobs-scraper&lt;/code&gt; as an MCP server in Claude, Cursor or ChatGPT, and ask &lt;em&gt;"Find 20 remote seed-stage startups hiring ML engineers that offer equity, with their websites."&lt;/em&gt; (&lt;a href="https://apify.com/gleanery_actors/wellfound-jobs-scraper" rel="noopener noreferrer"&gt;setup guide&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;If you do a compensation analysis with it, I'd love to see the charts.&lt;/p&gt;

</description>
      <category>startup</category>
      <category>data</category>
      <category>career</category>
      <category>webscraping</category>
    </item>
    <item>
      <title>The Arbeitsagentur Jobsuche API in 2026: search 1 million German jobs with Python (v6 endpoint)</title>
      <dc:creator>Gleanery Works</dc:creator>
      <pubDate>Wed, 21 Oct 2026 07:20:46 +0000</pubDate>
      <link>https://dev.to/gleaneryworks/the-arbeitsagentur-jobsuche-api-in-2026-search-1-million-german-jobs-with-python-v6-endpoint-41ea</link>
      <guid>https://dev.to/gleaneryworks/the-arbeitsagentur-jobsuche-api-in-2026-search-1-million-german-jobs-with-python-v6-endpoint-41ea</guid>
      <description>&lt;p&gt;The job board of Germany's Federal Employment Agency (Bundesagentur für Arbeit, &lt;strong&gt;arbeitsagentur.de/jobsuche&lt;/strong&gt;) lists &lt;strong&gt;over 1 million open jobs&lt;/strong&gt;: the largest job database in Germany, covering everything from nurses and electricians to software developers and apprenticeships. Its frontend talks to a JSON API that is open to everyone with a fixed public key.&lt;/p&gt;

&lt;p&gt;Many tutorials and wrappers still use the old &lt;code&gt;/pc/v4/jobs&lt;/code&gt; search endpoint, &lt;strong&gt;which now returns HTTP 403&lt;/strong&gt;. Here's what works today (checked October 2026).&lt;/p&gt;

&lt;h2&gt;
  
  
  Search: &lt;code&gt;/pc/v6/jobs&lt;/code&gt;
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;

&lt;span class="n"&gt;API&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://rest.arbeitsagentur.de/jobboerse/jobsuche-service/pc&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;HEADERS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;X-API-Key&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;jobboerse-jobsuche&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Accept&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;application/json&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;API&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;/v6/jobs&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;HEADERS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;was&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Softwareentwickler&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;   &lt;span class="c1"&gt;# what: job title or keyword
&lt;/span&gt;    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;wo&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Berlin&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;                &lt;span class="c1"&gt;# where: city or postal code
&lt;/span&gt;    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;umkreis&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;                 &lt;span class="c1"&gt;# radius in km
&lt;/span&gt;    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;size&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;page&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;maxErgebnisse&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;matching jobs&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;job&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ergebnisliste&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;job&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;stellenangebotsTitel&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;|&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;job&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;firma&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;|&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;job&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;stellenlokationen&lt;/span&gt;&lt;span class="sh"&gt;"&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;adresse&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ort&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each result has the title, employer (&lt;code&gt;firma&lt;/code&gt;), workplace address with coordinates, working-time flags, contract type (&lt;code&gt;vertragsdauer&lt;/code&gt;), home office flag (&lt;code&gt;homeofficemoeglich&lt;/code&gt;), publication date and the reference number (&lt;code&gt;referenznummer&lt;/code&gt;).&lt;/p&gt;

&lt;h3&gt;
  
  
  Parameters that work
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Parameter&lt;/th&gt;
&lt;th&gt;Values&lt;/th&gt;
&lt;th&gt;Meaning&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;was&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;text&lt;/td&gt;
&lt;td&gt;job title or keyword&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;wo&lt;/code&gt;, &lt;code&gt;umkreis&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;city/PLZ, km&lt;/td&gt;
&lt;td&gt;location and radius&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;angebotsart&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;1 job, 2 self-employment, 4 apprenticeship, 34 internship&lt;/td&gt;
&lt;td&gt;offer type&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;arbeitszeit&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;vz&lt;/code&gt;, &lt;code&gt;tz&lt;/code&gt;, &lt;code&gt;snw&lt;/code&gt;, &lt;code&gt;mj&lt;/code&gt;, joined with &lt;code&gt;;&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;full-time, part-time, shift/night/weekend, mini job&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;befristung&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;1 fixed-term, 2 permanent&lt;/td&gt;
&lt;td&gt;contract&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;veroeffentlichtseit&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;0, 1, 7, 14, 28&lt;/td&gt;
&lt;td&gt;published within N days (other values are ignored)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;zeitarbeit&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;false&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;exclude temp agencies (Zeitarbeit)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;pav&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;false&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;exclude private placement agencies&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;arbeitgeber&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;exact employer name&lt;/td&gt;
&lt;td&gt;one employer&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;page&lt;/code&gt;, &lt;code&gt;size&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;size up to 100&lt;/td&gt;
&lt;td&gt;pagination&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Two gotchas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;10,000 results max per query.&lt;/strong&gt; &lt;code&gt;page * size&lt;/code&gt; above 10,000 returns HTTP 400. Split big searches by location or date.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;There's no home office search parameter&lt;/strong&gt; in v6. Filter on &lt;code&gt;homeofficemoeglich == True&lt;/code&gt; yourself.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The response also contains &lt;code&gt;facetten&lt;/code&gt; (facet counts per occupation, city, employer, working time…), which is handy for labor-market statistics without downloading jobs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Salaries
&lt;/h2&gt;

&lt;p&gt;About a quarter of listings state pay:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;job&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ergebnisliste&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gehaltsspanneVon&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;job&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;          &lt;span class="c1"&gt;# range
&lt;/span&gt;        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;job&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gehaltsspanneVon&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;-&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;job&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gehaltsspanneBis&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;job&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;verguetungsangabe&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;festgehalt&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;job&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;              &lt;span class="c1"&gt;# fixed amount
&lt;/span&gt;        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;job&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;festgehalt&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;job&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;verguetungsangabe&lt;/span&gt;&lt;span class="sh"&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;verguetungsangabe&lt;/code&gt; is the unit: &lt;code&gt;JAHRESGEHALT&lt;/code&gt; (yearly), &lt;code&gt;STUNDENLOHN&lt;/code&gt; (hourly) or &lt;code&gt;KEINE_ANGABEN&lt;/code&gt; (none).&lt;/p&gt;

&lt;h2&gt;
  
  
  Details: still &lt;code&gt;/pc/v4/jobdetails&lt;/code&gt;, base64-encoded
&lt;/h2&gt;

&lt;p&gt;The full description is on a separate endpoint. Unlike search, it's still v4, and it wants the reference number &lt;strong&gt;base64-encoded&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;base64&lt;/span&gt;

&lt;span class="n"&gt;ref&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ergebnisliste&lt;/span&gt;&lt;span class="sh"&gt;"&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;referenznummer&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;enc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;base64&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;b64encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;()).&lt;/span&gt;&lt;span class="nf"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;detail&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;API&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;/v4/jobdetails/&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;enc&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;HEADERS&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;detail&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;stellenangebotsBeschreibung&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;][:&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;detail&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;istArbeitnehmerUeberlassung&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;detail&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;allianzpartnerName&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The details add the description, the temp-agency and private-recruiter flags, and &lt;code&gt;allianzpartnerName&lt;/code&gt;/&lt;code&gt;allianzpartnerUrl&lt;/code&gt;. Careful: the "Allianzpartner" is whoever delivered the posting, which is often a partner job board (jobvector, yourfirm…) and not the employer, so don't treat its URL as the company website unless the names match.&lt;/p&gt;

&lt;p&gt;The public job page is &lt;code&gt;https://www.arbeitsagentur.de/jobsuche/jobdetail/{referenznummer}&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Skip the plumbing
&lt;/h2&gt;

&lt;p&gt;If you'd rather not handle pagination, the 10k cap, detail requests, salary normalization and English field names yourself, I packaged all of this as an Apify actor: &lt;a href="https://apify.com/gleanery_actors/arbeitsagentur-jobs-scraper" rel="noopener noreferrer"&gt;Arbeitsagentur Jobs Scraper&lt;/a&gt;. It returns flat JSON (&lt;code&gt;title&lt;/code&gt;, &lt;code&gt;companyName&lt;/code&gt;, &lt;code&gt;city&lt;/code&gt;, &lt;code&gt;salaryMin&lt;/code&gt;, &lt;code&gt;salaryMax&lt;/code&gt;, &lt;code&gt;salaryInterval&lt;/code&gt;, &lt;code&gt;remote&lt;/code&gt;, &lt;code&gt;isTempAgency&lt;/code&gt;…), adds filters like &lt;code&gt;remoteOnly&lt;/code&gt;, &lt;code&gt;minSalaryYearly&lt;/code&gt; and &lt;code&gt;excludeTempAgencies&lt;/code&gt;, and has a monitoring mode for daily feeds. It costs $0.40 per 1,000 jobs.&lt;/p&gt;

&lt;h3&gt;
  
  
  For AI agents
&lt;/h3&gt;

&lt;p&gt;It's also callable as an MCP tool, for example from Claude or Cursor:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://mcp.apify.com?tools=gleanery_actors/arbeitsagentur-jobs-scraper
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ask &lt;em&gt;"find part-time nursing jobs in Hamburg posted this week, direct employers only"&lt;/em&gt; and the agent fills in the input. More job and B2B data tools for agents: &lt;a href="https://github.com/gleanery-works/job-and-supplier-data-mcp" rel="noopener noreferrer"&gt;github.com/gleanery-works/job-and-supplier-data-mcp&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>python</category>
      <category>api</category>
      <category>germany</category>
      <category>jobs</category>
    </item>
    <item>
      <title>Get every open job from Greenhouse, Lever and Ashby in 40 lines of Python</title>
      <dc:creator>Gleanery Works</dc:creator>
      <pubDate>Tue, 20 Oct 2026 12:45:53 +0000</pubDate>
      <link>https://dev.to/gleaneryworks/get-every-open-job-from-greenhouse-lever-and-ashby-in-40-lines-of-python-5fdg</link>
      <guid>https://dev.to/gleaneryworks/get-every-open-job-from-greenhouse-lever-and-ashby-in-40-lines-of-python-5fdg</guid>
      <description>&lt;p&gt;If you want to build a job board, track which companies are hiring, or benchmark salaries, you don't need to scrape HTML. Most companies' careers pages are hosted by an &lt;strong&gt;applicant tracking system (ATS)&lt;/strong&gt;, and the three most common ones with startups (Greenhouse, Lever and Ashby) all have &lt;strong&gt;public, unauthenticated JSON endpoints&lt;/strong&gt;. The careers page itself calls them.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Find out which ATS a company uses
&lt;/h2&gt;

&lt;p&gt;Open the careers page and click any job. The URL tells you:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;URL contains&lt;/th&gt;
&lt;th&gt;ATS&lt;/th&gt;
&lt;th&gt;Slug&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;boards.greenhouse.io/stripe&lt;/code&gt; or &lt;code&gt;job-boards.greenhouse.io/stripe&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Greenhouse&lt;/td&gt;
&lt;td&gt;&lt;code&gt;stripe&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;jobs.lever.co/palantir&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Lever&lt;/td&gt;
&lt;td&gt;&lt;code&gt;palantir&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;jobs.ashbyhq.com/openai&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Ashby&lt;/td&gt;
&lt;td&gt;&lt;code&gt;openai&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;If the careers page lives on the company's own domain, view the source and search for those hostnames: the job list is usually embedded from one of them.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Call the endpoint
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;

&lt;span class="n"&gt;HEADERS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;User-Agent&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;my-job-tracker/1.0 (you@example.com)&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;greenhouse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;slug&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://boards-api.greenhouse.io/v1/boards/&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;slug&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;/jobs&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                     &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;true&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;HEADERS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;jobs&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
        &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;title&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;title&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;location&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;location&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
               &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;department&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;departments&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;or&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="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
               &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;url&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;absolute_url&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;posted&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;first_published&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;lever&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;slug&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;skip&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;page&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://api.lever.co/v0/postings/&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;slug&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                            &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;mode&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;json&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;skip&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;skip&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;limit&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
                            &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;HEADERS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;title&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;text&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;location&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;categories&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;location&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                   &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;department&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;categories&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;team&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;url&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;hostedUrl&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
                   &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;remote&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;workplaceType&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;remote&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                   &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;salary&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;salaryRange&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;break&lt;/span&gt;
        &lt;span class="n"&gt;skip&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;ashby&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;slug&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://api.ashbyhq.com/posting-api/job-board/&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;slug&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                     &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;includeCompensation&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;true&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;HEADERS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;jobs&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
        &lt;span class="n"&gt;comp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;compensation&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="p"&gt;{}).&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;compensationTierSummary&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;title&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;title&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;location&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;location&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
               &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;department&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;department&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;url&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;jobUrl&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
               &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;remote&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;isRemote&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;salary&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;comp&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;job&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;ashby&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;openai&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;job&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it: no API key, no headless browser, and no HTML parsing.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Salary ranges
&lt;/h2&gt;

&lt;p&gt;Pay-transparency laws in New York, California, Colorado, Washington and soon the EU mean many postings now carry a salary range, and the APIs expose it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Ashby:&lt;/strong&gt; &lt;code&gt;compensation.summaryComponents[]&lt;/code&gt; has &lt;code&gt;minValue&lt;/code&gt;, &lt;code&gt;maxValue&lt;/code&gt;, &lt;code&gt;currencyCode&lt;/code&gt; and &lt;code&gt;interval&lt;/code&gt; per component (salary, equity, bonus).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lever:&lt;/strong&gt; &lt;code&gt;salaryRange&lt;/code&gt; with &lt;code&gt;min&lt;/code&gt;, &lt;code&gt;max&lt;/code&gt;, &lt;code&gt;currency&lt;/code&gt;, &lt;code&gt;interval&lt;/code&gt; (e.g. &lt;code&gt;per-year-salary&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Greenhouse:&lt;/strong&gt; not in the list response. Fetch each job with &lt;code&gt;?pay_transparency=true&lt;/code&gt; and read &lt;code&gt;pay_input_ranges[]&lt;/code&gt; (&lt;code&gt;min_cents&lt;/code&gt;, &lt;code&gt;max_cents&lt;/code&gt;, &lt;code&gt;currency_type&lt;/code&gt;).
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;greenhouse_pay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;slug&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;job_id&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://boards-api.greenhouse.io/v1/boards/&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;slug&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;/jobs/&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;job_id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                     &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;pay_transparency&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;true&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;HEADERS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;min_cents&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;max_cents&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;currency_type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
            &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;pay_input_ranges&lt;/span&gt;&lt;span class="sh"&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;h2&gt;
  
  
  4. Gotchas I hit
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Greenhouse EU boards&lt;/strong&gt; live on &lt;code&gt;boards-api.eu.greenhouse.io&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lever EU accounts&lt;/strong&gt; use &lt;code&gt;api.eu.lever.co&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Slugs are not company names.&lt;/strong&gt; "Hugging Face" might be &lt;code&gt;huggingface&lt;/code&gt; or &lt;code&gt;hugging-face&lt;/code&gt;, and on some ATSs a generic slug like &lt;code&gt;remote&lt;/code&gt; or &lt;code&gt;figure&lt;/code&gt; belongs to a different company. Check the company name the API returns before trusting a guessed slug.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Be polite.&lt;/strong&gt; These endpoints serve real careers pages. Cache, keep concurrency low and send a User-Agent with contact info.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Beyond these three
&lt;/h2&gt;

&lt;p&gt;Enterprise employers use &lt;strong&gt;Workday&lt;/strong&gt; (a POST API with a 20-item page limit and a &lt;code&gt;total&lt;/code&gt; that only appears on page 1), and European companies often use &lt;strong&gt;Personio&lt;/strong&gt; (XML), &lt;strong&gt;Recruitee&lt;/strong&gt;, &lt;strong&gt;SmartRecruiters&lt;/strong&gt; or &lt;strong&gt;Workable&lt;/strong&gt;. I documented the endpoints for 11 ATSs, with their pagination quirks and salary fields, here: &lt;strong&gt;&lt;a href="https://github.com/gleanery-works/ats-job-apis" rel="noopener noreferrer"&gt;github.com/gleanery-works/ats-job-apis&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;If you'd rather not maintain eleven integrations, I also run them as a hosted tool, &lt;a href="https://apify.com/gleanery_actors/career-site-jobs-scraper" rel="noopener noreferrer"&gt;Career Site Jobs Scraper&lt;/a&gt;. You give it company names, and it finds each company's ATS and returns one normalized schema with salary min/max. It can also return only jobs that are new since the last run, which is handy for hiring-signal alerts. It's pay per result ($1 per 1,000 jobs), and Apify's free monthly credit covers small projects.&lt;/p&gt;

&lt;h2&gt;
  
  
  Giving an AI agent access to job data
&lt;/h2&gt;

&lt;p&gt;If the consumer is an LLM agent rather than your own code, you can skip the integration entirely and expose the tool over MCP:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;claude mcp add &lt;span class="nt"&gt;--transport&lt;/span&gt; http &lt;span class="nb"&gt;jobs&lt;/span&gt; &lt;span class="s2"&gt;"https://mcp.apify.com?tools=gleanery_actors/career-site-jobs-scraper"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then ask: &lt;em&gt;"Which of Datadog, Snowflake and Figma opened data-engineering roles this week, and what do they pay?"&lt;/em&gt; The agent calls the tool with &lt;code&gt;{"companies": [...], "titleKeywords": ["data engineer"], "postedWithinDays": 7}&lt;/code&gt; and gets normalized JSON back. Setup for Cursor, Claude Desktop and VS Code is in &lt;a href="https://github.com/gleanery-works/job-and-supplier-data-mcp" rel="noopener noreferrer"&gt;gleanery-works/job-and-supplier-data-mcp&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;What are you building with job data? I'm curious which ATSs people still miss.&lt;/p&gt;

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