# Hiring Intent Leads — Greenhouse & Lever Job Boards (`samstorm/hiring-intent-lead-scraper`) Actor

Find target companies hiring on public Greenhouse and Lever job boards. Supply board URLs, filter roles and locations, and export company records with job links. No provider API key needed. Optional public-email enrichment uses employer websites you supply.

- **URL**: https://apify.com/samstorm/hiring-intent-lead-scraper.md
- **Developed by:** [Sam Kleespies](https://apify.com/samstorm) (community)
- **Categories:** Lead generation
- **Features:** Limited permissions
- **Stats:** 106 total users, 2 monthly users, 96.7% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $50.00 / 1,000 enriched hiring intent leads

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

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

## Hiring Intent Leads — Public Company Job Boards

Find companies with matching open roles on **Greenhouse and Lever**, with a direct job link and source evidence for every returned company. Use hiring activity to prioritize account research, recruitment services, or relevant B2B outreach. A job posting does not prove buying intent, an approved budget, or a decision-maker's identity.

**No paid data-provider API key is needed in public-board mode.** Apify Actor fees and platform usage still apply. You supply target companies' board URLs; this is not a whole-web company discovery service.

### Try a small run

[Open the two-company public-board example](https://apify.com/samstorm/hiring-intent-lead-scraper/examples/public-job-boards-2-company-hiring-sample).

Keep the prefilled public-board mode and two example companies, set the title to Engineer, leave location blank, and request two company records. The sample disables email enrichment because it does not supply employer websites. Set a small run-cost limit and timeout before starting. Public postings change; a valid board can have no matching jobs.

Replace the examples with your own Greenhouse or Lever board URLs. String URLs work, or use objects with url, companyName, and companyWebsite. Only add companyWebsite when you have verified the employer's public website; it is used for optional email extraction and is marked as input-supplied in the output.

Example input:

```json
{
  "source": "job_boards",
  "jobBoards": [
    { "url": "https://job-boards.greenhouse.io/greenhouse", "companyName": "Greenhouse" },
    { "url": "https://jobs.lever.co/spotify", "companyName": "Spotify" }
  ],
  "jobTitle": "Engineer",
  "location": "",
  "maxResults": 2,
  "enrichEmails": false,
  "verifyEmails": false,
  "outputFormat": "full"
}
```

### Supported sources and coverage

- Greenhouse: boards.greenhouse.io or job-boards.greenhouse.io company boards.
- Lever: jobs.lever.co and jobs.eu.lever.co company boards.
- Google Jobs: retained as an explicitly unreliable legacy option. Recent tests were blocked. Use board mode when you have target-company URLs.

Automatic mode chooses board mode when jobBoards is supplied; otherwise it keeps the legacy Google Jobs behavior for existing integrations. The new prefilled example explicitly selects board mode. No silent substitution of unrelated companies occurs.

Board mode accepts up to 20 boards. It returns at most one representative matching job per company, not every vacancy, and deduplicates shared company names or supplied websites. The result cap is a ceiling; two boards can return no more than two company records. Title and location filters use case-insensitive word matching. Blank filters include any role/location. Remote matching requires source evidence; locations are not geocoded.

Lever pages are bounded to 1,000 postings per board and Greenhouse matching to 5,000. Incomplete coverage is reported in OUTPUT_SUMMARY. All source failures fail the run; partial results identify failed/capped boards. A valid completed search with no matches returns zero records. A zero-match search with source failures or a scan cap fails explicitly.

### Output and email evidence

Full output contains companyName, companyNameSource, companyWebsite, companyWebsiteSource, jobTitle, jobLocation, jobSource, jobUrl, jobBoardUrl, jobId, hiringSignal, email, verification evidence, allEmails, and scrapedAt. Name provenance is input, job_board, or board_identifier. Employer websites are never inferred from the board slug. Missing contact information remains blank.

Email extraction is optional and requires a usable employer website. SMTP verification can be blocked or inconclusive. A true emailVerified value requires acceptance of the recipient and rejection of a random-recipient probe. DNS MX evidence is separate, and no delivery or bounce rate is guaranteed. HubSpot and Salesforce layouts may require custom-field mapping.

### Repeat account monitoring

Save your target-board list as an Apify task and rerun it on your chosen schedule. Compare jobId/jobUrl and company identifiers between datasets to find changed hiring activity. This actor does not persist a cross-run change history or send outreach. Use the source posting to assess relevance before contacting a business.

### Pricing and support

The current base event is $50 per 1,000 returned company records. For example, two returned records are $0.10 in base result fees, before any other configured events, platform usage, or applicable plan discounts. A returned company record is chargeable even if it has no email. Check the live Pricing tab for the complete current charges. Provider API credits are not needed for Greenhouse/Lever reads.

For an issue, include a current run link, source mode, board URLs, filters, and the expected versus observed result. Do not post API tokens or private customer data.

Source references: [Greenhouse public job-board API](https://docs.greenhouse.io/job-board.html) and [Lever public postings API](https://github.com/lever/postings-api).

# Actor input Schema

## `source` (type: `string`):

Public company boards require target board URLs and no paid provider key. This mode does not discover companies across the whole web.

## `jobBoards` (type: `array`):

1–20 public Greenhouse or Lever board URLs. Use URL strings or objects with url, optional companyName, and optional companyWebsite. Employer websites are never guessed. One matching company record per board, deduplicated by supplied company name/website.

## `jobTitle` (type: `string`):

Optional in board mode: case-insensitive title words; all words must match. Leave blank for any role. Required in legacy Google Jobs mode. A vacancy is a hiring signal, not proof of purchase intent.

## `location` (type: `string`):

Optional in board mode: all entered words must appear in the source location/workplace text. Leave blank for all locations. Remote works when explicitly stated by the source. No geocoding or radius matching.

## `maxResults` (type: `integer`):

1–200 company records. Board mode returns at most one matching record per supplied board (up to 20 boards). Legacy Google mode also collapses duplicate employers.

## `enrichEmails` (type: `boolean`):

Extract public emails only from an employer website. In board mode supply companyWebsite in the relevant jobBoards object; no company domains are guessed. No website means no email enrichment for that record.

## `verifyEmails` (type: `boolean`):

Attempt DNS MX and SMTP checks. MX only validates the mail domain; mailbox checks can be blocked or inconclusive. A true emailVerified flag requires SMTP acceptance plus rejection of a random address and does not guarantee delivery.

## `outputFormat` (type: `string`):

Choose full details or convenient HubSpot/Salesforce column layouts. CRM imports may require field mapping or custom properties.

## Actor input object example

```json
{
  "source": "job_boards",
  "jobBoards": [
    {
      "url": "https://job-boards.greenhouse.io/greenhouse",
      "companyName": "Greenhouse"
    },
    {
      "url": "https://jobs.lever.co/spotify",
      "companyName": "Spotify"
    }
  ],
  "jobTitle": "Engineer",
  "location": "",
  "maxResults": 2,
  "enrichEmails": false,
  "verifyEmails": false,
  "outputFormat": "full"
}
```

# Actor output Schema

## `results` (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 = {
    "source": "job_boards",
    "jobBoards": [
        {
            "url": "https://job-boards.greenhouse.io/greenhouse",
            "companyName": "Greenhouse"
        },
        {
            "url": "https://jobs.lever.co/spotify",
            "companyName": "Spotify"
        }
    ],
    "jobTitle": "Engineer",
    "location": "",
    "maxResults": 2,
    "enrichEmails": false,
    "verifyEmails": false
};

// Run the Actor and wait for it to finish
const run = await client.actor("samstorm/hiring-intent-lead-scraper").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 = {
    "source": "job_boards",
    "jobBoards": [
        {
            "url": "https://job-boards.greenhouse.io/greenhouse",
            "companyName": "Greenhouse",
        },
        {
            "url": "https://jobs.lever.co/spotify",
            "companyName": "Spotify",
        },
    ],
    "jobTitle": "Engineer",
    "location": "",
    "maxResults": 2,
    "enrichEmails": False,
    "verifyEmails": False,
}

# Run the Actor and wait for it to finish
run = client.actor("samstorm/hiring-intent-lead-scraper").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 '{
  "source": "job_boards",
  "jobBoards": [
    {
      "url": "https://job-boards.greenhouse.io/greenhouse",
      "companyName": "Greenhouse"
    },
    {
      "url": "https://jobs.lever.co/spotify",
      "companyName": "Spotify"
    }
  ],
  "jobTitle": "Engineer",
  "location": "",
  "maxResults": 2,
  "enrichEmails": false,
  "verifyEmails": false
}' |
apify call samstorm/hiring-intent-lead-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,samstorm/hiring-intent-lead-scraper"
        }
    }
}
```

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/SbCglJ6T4IzZYtJ87/builds/Vq6cIFz1HBuFOJuk3/openapi.json
