# Wellfound Jobs Scraper - Startup Jobs & Salary Data (`cirkit/wellfound-jobs-scraper`) Actor

Scrape startup jobs from Wellfound (AngelList): job title, salary range, equity range, remote policy, experience, full description, company size, stage, YC and investor badges. No login.

- **URL**: https://apify.com/cirkit/wellfound-jobs-scraper.md
- **Developed by:** [Crikit](https://apify.com/cirkit) (community)
- **Categories:** Jobs, Lead generation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.70 / 1,000 job listings

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

### What is Wellfound Jobs Scraper?

**Wellfound Jobs Scraper** lets you extract startup job listings from Wellfound (formerly AngelList Talent) at scale, helping you build recruiting pipelines, track hiring signals across the startup market, and feed job boards with fresh, structured data. Search by role and city, get back every listing with its salary band, equity band, remote policy and the company behind it.

- 🎯 **Track startup hiring signals:** see which startups are actively hiring, growing fast, YC funded or backed by top investors, and pick up on expansion before it hits the news.
- 💰 **Benchmark salary and equity:** every listing carries a parsed salary range and equity range as numbers, so you can chart compensation by role, city and company stage without cleaning strings first.
- 🧲 **Build recruiting and sales lists:** company name, tagline, size, stage, logo and Wellfound profile URL on every row, ready for a CRM or an outreach sequence.
- 📋 **Power a niche job board:** full job descriptions in markdown, remote policy, job type and posting date, refreshed on whatever schedule you set.
- 🔍 **Research a market before you enter it:** count how many startups in a city are hiring for a role, and at what pay.

Wellfound has no public jobs API, and its own site stops serving new results after roughly 47 pages per search. Wellfound Jobs Scraper walks that full depth automatically, stops the moment the site starts repeating itself, and deduplicates across every search you queue, so you never pay twice for the same listing.

### What data does Wellfound Jobs Scraper extract?

**The job**

- 🏷 Job title and Wellfound's own normalised role title (`title`, `primaryRoleTitle`)
- 🔗 Direct link to the listing and to the company profile (`jobUrl`, `companyUrl`)
- 💲 Raw compensation string exactly as Wellfound shows it (`compensation`)
- 💵 Parsed salary range with currency (`salaryMin`, `salaryMax`, `salaryCurrency`)
- 📈 Parsed equity range as percentages (`equityMin`, `equityMax`)
- 🏠 Remote policy: remote, onsite, or onsite-or-remote, plus work-from-home flexibility (`remoteKind`, `isRemote`, `wfhFlexible`)
- 📍 Office locations and the countries a remote role is open to (`locationNames`, `acceptedRemoteLocationNames`)
- 📆 Employment type: full-time, contract or internship (`jobType`)
- 🎓 Years of experience required, minimum and maximum (`yearsExperienceMin`, `yearsExperienceMax`)
- 🕒 Date the listing went live, as an ISO timestamp (`postedAt`)
- 📝 The complete job description in markdown (`description`)
- ⚙️ Which applicant tracking system the role is syndicated from, for example Ashby, Greenhouse or Lever (`atsSource`)

**The startup behind it**

- 🏢 Company name, slug, id and one-line tagline (`companyName`, `companyTagline`)
- 👥 Headcount band, for example "11-50 employees" (`companySize`)
- 🚀 Funding stage: Early, Growth or Scale (`companyStage`)
- 🟠 Y Combinator funded flag (`isYcFunded`)
- 💼 Top investors flag and $1B-plus valuation badge (`hasTopInvestors`, `companyBadges`)
- 🔥 Actively hiring and growing fast flags (`isActivelyHiring`, `isGrowingFast`)
- ⏱ How fast the company replies to applicants, for example "Responds within a day" (`responseSpeed`)
- ⭐️ Glassdoor rating where Wellfound publishes one (`glassdoorRating`)
- 🖼 Company logo URL (`companyLogoUrl`)

**Provenance on every row**

- 🔎 The role and location you searched, and what Wellfound actually matched them to (`searchRole`, `searchLocation`, `matchedRole`, `matchedLocation`)
- 🌐 The exact page the row came from (`sourceUrl`) and when it was scraped (`scrapedAt`)

### How to use Wellfound Jobs Scraper

1. Click **Try for free** and open the input form.
2. Type the roles you want in plain English, one per line, for example `software engineer`, `product manager`, `data scientist`.
3. Add cities in **Locations**, one per line, for example `new york`, `san francisco`, `london`. Leave it empty to search every location.
4. Set **Max results** to whatever you want to spend, then click **Start**.
5. Export to JSON, CSV, Excel or Google Sheets, or pull the dataset straight from the Apify API.

Every role is combined with every location, so three roles and four cities is twelve searches in one run.

### Input

```json
{
  "roles": ["software engineer", "product manager"],
  "locations": ["new york", "san francisco"],
  "maxItems": 500,
  "includeDescription": true,
  "proxyConfiguration": { "useApifyProxy": true }
}
```

Power users can skip the role and location builder and paste Wellfound URLs directly:

```json
{
  "startUrls": [
    "https://wellfound.com/role/l/software-engineer/new-york",
    "https://wellfound.com/role/r/data-scientist",
    "https://wellfound.com/location/london"
  ],
  "maxItems": 1000
}
```

| Field | Type | Default | What it does |
|---|---|---|---|
| `roles` | array of strings | `["software engineer"]` | Roles to search, in plain English |
| `locations` | array of strings | `[]` | Cities to search. Empty means all locations |
| `startUrls` | array of strings | `[]` | Wellfound `/role/r/`, `/role/l/` or `/location/` URLs |
| `maxItems` | integer | `200` | Hard cap on rows. `0` means no limit |
| `includeDescription` | boolean | `true` | Include the full job description text |
| `maxPagesPerQuery` | integer | `47` | How deep to page into one search |
| `proxyConfiguration` | object | Apify Proxy | Datacenter proxy is enough, and it is the cheapest |

### Output

One row per job listing. Trimmed real record:

```json
{
  "jobId": "3336630",
  "title": "Senior Software Engineer",
  "jobUrl": "https://wellfound.com/company/shelfcycle/jobs/3336630-senior-software-engineer",
  "primaryRoleTitle": "Software Engineer",
  "jobType": "full-time",
  "isRemote": true,
  "remoteKind": "onsite or remote",
  "locationNames": ["New York City"],
  "compensation": "$160k – $200k • 0.25% – 0.5%",
  "salaryMin": 160000,
  "salaryMax": 200000,
  "salaryCurrency": "USD",
  "equityMin": 0.25,
  "equityMax": 0.5,
  "yearsExperienceMin": 5,
  "postedAt": "2026-09-01T14:32:48.000Z",
  "companyName": "ShelfCycle",
  "companyTagline": "Modern OS for chemical distributors",
  "companySize": "1-10 employees",
  "companyStage": "Early Stage",
  "companyBadges": ["Actively Hiring", "Top 10% of responders", "B2B", "Early Stage"],
  "isYcFunded": false,
  "isActivelyHiring": true,
  "responseSpeed": "Top 10% of responders",
  "searchRole": "software engineer",
  "matchedRole": "Software Engineer",
  "matchedLocation": "New York",
  "scrapedAt": "2026-09-04T13:36:54.659Z"
}
```

The dataset ships with two ready-made table views. **Overview** gives you job title, company, location, remote policy, salary band, equity band, company size, posting date and link. **Companies** gives you the startup side on its own: tagline, size, stage, YC and investor flags, response speed and Glassdoor rating.

### How much does it cost to scrape Wellfound?

One flat price of **$0.70 per 1,000 job listings**. No actor start fee, no per-page fee, no surcharge for the full job description, no separate charge for company data.

| Job listings | Cost |
|---|---|
| 1,000 | $0.70 |
| 10,000 | $7.00 |
| 100,000 | $70.00 |

Rows are deduplicated by job id across every search in a run, so overlapping queries such as "software engineer" and "backend engineer" in the same city never bill you twice for the same listing. Other Wellfound scrapers on the Store charge between $0.99 and $5.00 per 1,000, and several add a per-run start fee on top.

### Measured coverage

Measured over 832 job rows across 15 test runs on 2026-09-04, spanning six roles and seven cities:

| Field | Coverage | Note |
|---|---|---|
| `title`, `companyName`, `jobUrl`, `postedAt`, `jobType`, `remoteKind` | 100% | Always present |
| `companyLogoUrl`, `primaryRoleTitle` | 100% | Always present |
| `description` | 100% | When `includeDescription` is on |
| `companySize` | 99% | |
| `companyTagline` | 97% | |
| `companyBadges` | 93% | Empty when a company has earned no badges |
| `locationNames` | 87% | Empty on remote-only roles |
| `compensation` | 81% | Wellfound shows pay on roughly four listings in five |
| `salaryMin`, `salaryMax`, `salaryCurrency` | 76% | Parsed from `compensation` where a salary is quoted |
| `companyStage` | 70% | |
| `atsSource` | 56% | Only for roles syndicated from an ATS |
| `yearsExperienceMin` | 41% | Only when the company set it |
| `equityMin`, `equityMax` | 26% | Only when the listing quotes equity |
| `responseSpeed` | 24% | Only for companies with enough application history |
| `glassdoorRating` | 9% | Only where Wellfound surfaces a Glassdoor score |

Throughput measured on the same date: 1,249 unique listings from a single role search in 31 seconds, zero duplicates.

### Limits

- **Roughly 1,300 listings per search.** Wellfound stops serving new results after about 47 pages and then quietly repeats page 1. The scraper detects that and stops rather than billing you for duplicates. For more volume, split the search: add cities, or use narrower role names.
- **Keyword search is not supported.** `wellfound.com/jobs?q=...` renders its results in the browser and carries no data in the page source, so it cannot be scraped this way. Use role names and cities instead, which is how Wellfound's own indexed pages are organised.
- **Unrecognised role names return a generic list.** Wellfound answers an unknown role with a general job feed instead of an error. When that happens the run logs a warning and every affected row carries `matchedRole: null`, so you can filter them out.
- **Applicant counts and recruiter contact details are not available.** Those sit behind a Wellfound login, and this scraper uses no credentials of any kind.
- **Company pages are not scraped.** Only the company data Wellfound includes in its search results, which is the block listed above.

### FAQ

#### Is it legal to scrape Wellfound?

Wellfound Jobs Scraper reads only public job listing pages that Wellfound publishes for search engines. It uses no login, no cookies and no credentials, and it collects no personal data about candidates. Job listings and company profiles are business information. You are responsible for how you use the data you collect, including compliance with Wellfound's terms and with any applicable data protection law in your jurisdiction.

#### Do I need a Wellfound account?

No. The scraper never signs in and never asks you for credentials.

#### Can I use Wellfound Jobs Scraper as an API?

Yes. Every actor on Apify is an API endpoint. Start a run and collect the dataset with a single HTTP call, or use the official clients. See the [Apify API docs](https://docs.apify.com/api/v2).

#### Can I use this in Python?

Yes, with `apify-client`:

```python
from apify_client import ApifyClient

client = ApifyClient("YOUR_APIFY_TOKEN")
run = client.actor("YOUR_USERNAME/wellfound-jobs-scraper").call(run_input={
    "roles": ["software engineer"],
    "locations": ["new york"],
    "maxItems": 500,
})
for job in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(job["title"], job["companyName"], job["salaryMin"], job["salaryMax"])
```

#### Can I integrate Wellfound Jobs Scraper with other apps?

Yes. Apify has native integrations for Zapier, Make, Slack, Google Sheets, Google Drive, GitHub and Airtable, plus generic webhooks that fire when a run finishes. Point a webhook at your own service and treat the scraper as a data feed.

#### How do I schedule Wellfound Jobs Scraper to run automatically?

Use Apify Schedules. Daily at 7am is a good cadence for hiring signals: new listings show up with a fresh `postedAt`, so you can diff against yesterday's dataset to get only what changed.

#### Why did I get fewer results than expected?

Three usual causes. First, `maxItems` is doing its job. Second, the role and city combination is genuinely thin: "software engineer in Reykjavik" returns nothing, and the run tells you so in a single row with `noResults: true`. Third, you hit the roughly 1,300 listings per search ceiling described under Limits. Check the run log, which states how many new rows each page contributed.

#### Why is the salary missing on some rows?

Because Wellfound does not have it. Roughly one listing in five quotes no pay at all. Rows carry `compensation: null` in that case rather than a guess.

#### What does "onsite or remote" mean in `remoteKind`?

It is Wellfound's own three-way classification, passed through unchanged: `remote`, `onsite`, or `onsite or remote` for roles the company will fill either way. `wfhFlexible` is a separate flag for onsite roles that allow work-from-home days.

#### Can I get a field that is not listed?

If Wellfound publishes it on the search pages, probably yes. Open an issue on the actor page and describe the field.

#### What happens if Wellfound blocks the scraper mid-run?

The run keeps whatever it has already collected, rotates to a fresh proxy exit address, and retries up to four times per page. If a search still cannot be read, that search is skipped and the rest of the run continues. Runs finish as succeeded with an explanatory row rather than failing, so a scheduled pipeline does not break.

### You might also like

- **Indeed Jobs Scraper** for mainstream job market coverage
- **ATS Job Boards Search Scraper** for Greenhouse, Ashby and Lever boards directly
- **Dice Tech Jobs Search Scraper** for US tech contract and permanent roles
- **Workday Jobs Search Scraper** for enterprise career sites
- **Glassdoor Company Scraper** for employer ratings and reviews

### Changelog

**0.1** (2026-09-04) - First release. Role, role plus city and city-wide search, salary and equity parsing across currencies, company badges, deduplication across searches, and automatic end-of-results detection.

# Actor input Schema

## `roles` (type: `array`):

Job roles to search, in plain English. One per line, for example "software engineer", "product manager", "data scientist". Each role is combined with every location below. Leave empty and fill in Locations only to get every role in those cities.

## `locations` (type: `array`):

Cities to search, one per line, for example "new york", "san francisco", "london", "remote". Leave empty to search every location for the roles above.

## `startUrls` (type: `array`):

Wellfound search URLs to scrape directly, one per line. Supported shapes: https://wellfound.com/role/r/<role>, https://wellfound.com/role/l/<role>/<city> and https://wellfound.com/location/<city>. Note that https://wellfound.com/jobs?q=... is not supported because that page renders its results in the browser and carries no data in the page source.

## `maxItems` (type: `integer`):

Hard cap on the total number of job rows returned across every search. Set to 0 for no limit. You are charged per row, so this is also your budget control.

## `includeDescription` (type: `boolean`):

Include the complete job description text on every row. Turn this off for a much smaller dataset when you only need titles, salaries and company data.

## `maxPagesPerQuery` (type: `integer`):

Safety cap on how deep to page into one search. Wellfound stops serving new results after page 47 and then repeats page 1, so 47 is the maximum and roughly 1,300 jobs per search.

## `proxyConfiguration` (type: `object`):

Apify Proxy settings. The default datacenter pool works against Wellfound and is the cheapest option; there is no need for residential proxies here.

## Actor input object example

```json
{
  "roles": [
    "software engineer"
  ],
  "locations": [
    "new york"
  ],
  "startUrls": [],
  "maxItems": 100,
  "includeDescription": true,
  "maxPagesPerQuery": 47,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `results` (type: `string`):

Everything this run collected as the Overview table: job title, company, location, remote policy, salary band, equity band, company size, posting date and link.

## `companies` (type: `string`):

The startup side on its own: company, tagline, headcount, funding stage, YC and top-investor flags, response speed and Glassdoor rating.

## `resultsCsv` (type: `string`):

The full result set as CSV, ready for a spreadsheet or a BI tool.

## `consoleRun` (type: `string`):

The Apify Console page for this run, including the live log.

# 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 = {
    "roles": [
        "software engineer"
    ],
    "locations": [
        "new york"
    ],
    "maxItems": 100,
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("cirkit/wellfound-jobs-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 = {
    "roles": ["software engineer"],
    "locations": ["new york"],
    "maxItems": 100,
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("cirkit/wellfound-jobs-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 '{
  "roles": [
    "software engineer"
  ],
  "locations": [
    "new york"
  ],
  "maxItems": 100,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call cirkit/wellfound-jobs-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,cirkit/wellfound-jobs-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/iqfNVxgtNaUwfTP8R/builds/bVeHzTWVMqekTTXIv/openapi.json
