DEV Community

Big Man
Big Man

Posted on

How to get job listings from Greenhouse job boards with an API (Python, Node or no code)

Thousands of companies, from startups to Airbnb, Discord and Robinhood, host their careers page on Greenhouse. If you track hiring at a list of companies, or run a job board or newsletter, checking each careers page by hand doesn't scale.

This tutorial uses Greenhouse Jobs Scraper, an Apify actor I built. It returns every open job from any company's Greenhouse board: title, company, locations, departments, posted date, the salary range when the company publishes one, the full description and the apply link. You can filter by title, location, department and date, and an only-new mode suits scheduled runs. The full examples are on GitHub: auto-actor/greenhouse-jobs-scraper.

What people use it for

  • A daily feed of new openings at a list of target companies with onlyNew: true.
  • Salary benchmarking from the pay ranges companies publish.
  • Tracking which teams a company is hiring for (departments) as a sales or investment signal.

Input

You only need the board name: airbnb in job-boards.greenhouse.io/airbnb, or the full URL.

{"boards": ["discord"], "maxItems": 50}
Enter fullscreen mode Exit fullscreen mode
Field What it does
boards Companies to scrape: the board name from the careers URL (airbnb in job-boards.greenhouse.io/airbnb) or the full URL.
titleSearch Keep only jobs whose title contains any of these words.
titleExclusionSearch Drop jobs whose title contains any of these words.
locationSearch Keep only jobs whose location or office contains any of these words.
departmentSearch Keep only jobs in a department whose name contains any of these words.
postedWithinDays Keep only jobs first published in the last N days.
includeSalary Fetch the pay range the company publishes for each job (empty when it doesn't publish one).
maxItems Stop after this many jobs in total across all boards.
onlyNew Skip jobs already returned by earlier runs (remembered for 180 days in the greenhouse-jobs-seen store of your account). Ideal for schedules.

Python

"""Run Greenhouse Jobs Scraper on Apify and print the results.

    pip install apify-client
    export APIFY_TOKEN=...   # Apify Console -> Settings -> Integrations
    python example.py
"""
import os

from apify_client import ApifyClient

client = ApifyClient(os.environ["APIFY_TOKEN"])

run = client.actor("daedal_quintuplet/greenhouse-jobs-scraper").call(
    run_input={
        "boards": [
            "discord"
        ],
        "maxItems": 50
    }
)

jobs = client.dataset(run["defaultDatasetId"]).iterate_items()
for job in jobs:
    print(job["title"], "|", job["organization"], "|", job["location"], "|", job.get("salary_min") or "no salary listed")
Enter fullscreen mode Exit fullscreen mode

Node.js

// Run Greenhouse Jobs Scraper on Apify and print the results.
//
//   npm install apify-client
//   APIFY_TOKEN=... node example.js     (token: Apify Console -> Settings -> Integrations)

const { ApifyClient } = require('apify-client');

async function main() {
    const client = new ApifyClient({ token: process.env.APIFY_TOKEN });

    const run = await client.actor('daedal_quintuplet/greenhouse-jobs-scraper').call({
        "boards": [
            "discord"
        ],
        "maxItems": 50
    });

    const { items } = await client.dataset(run.defaultDatasetId).listItems();
    for (const job of items) {
        console.log(job.title, '|', job.organization, '|', job.location, '|', job.salary_min || 'no salary listed');
    }
}

main().catch((err) => {
    console.error(err);
    process.exit(1);
});
Enter fullscreen mode Exit fullscreen mode

No code: one HTTP request

Works from n8n, Make, Zapier or curl:

curl -X POST "https://api.apify.com/v2/acts/daedal_quintuplet~greenhouse-jobs-scraper/run-sync-get-dataset-items?token=$APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"boards": ["discord"], "maxItems": 50}'
Enter fullscreen mode Exit fullscreen mode

What you get

One row per job:

Field Meaning
id Greenhouse job id
title Job title
organization Company
board Greenhouse board name
url Link to the job ad
apply_url Link to the application form
date_posted When the job was first published
date_updated When the ad was last updated
locations Every location listed
location Location text as shown on the board
departments Departments
offices Offices
salary_min Lowest published pay, when the company publishes a range
salary_max Highest published pay
salary_currency Pay currency
salary_title Label of the pay range
requisition_id Company's requisition id, when set
description_text Full job description as plain text
description_html Full job description as HTML
metadata Custom fields the company adds
scrapedAt When it was scraped

Notes

  • Works for any company whose careers page is hosted on Greenhouse; find the board name in the careers URL.
  • includeSalary costs one extra request per job; turn it off if you don't need pay ranges.

Price

$0.0012 per job ($1.20 per 1,000), paid per result, with no monthly fee. Apify's free plan includes $5 of usage a month, which is enough to try it. For companies that hire on Lever, Ashby, SmartRecruiters, Workday or Workable instead, there's a matching Career Site Jobs Scraper.

Links: Store page ยท GitHub examples

Top comments (0)