# Wellfound Jobs Scraper - $1 / 1000 Jobs (`scrapeunblocker/wellfound-jobs-scraper`) Actor

Scrape Wellfound (AngelList Talent) startup jobs by role, location or remote: full description, salary and equity ranges, remote policy, experience, posted date and the hiring startup. Optional job page details (skills, visa, funding, founders). $1 / 1000 jobs.

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

## Pricing

from $1.00 / 1,000 jobs

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?

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

## Wellfound Jobs Scraper

Scrape **Wellfound (formerly AngelList Talent) startup jobs** as clean structured JSON - by role, by location, remote only, or from any Wellfound search URL. Every job comes with its **full description**, the **salary range** and **equity range** parsed into numbers, job type, locations, remote policy, accepted remote locations, years of experience, posting date and the **hiring startup** (name, tagline, size, stage, badges such as "Actively Hiring", "YC Funded" or "Top Investors").

Turn on **job page details** to also get skills, visa sponsorship, relocation, hiring contact, preferred timezones, salary period and the company's funding and founders - at the same price per job.

### Features

- **Search by role and location** - `software engineer`, `product-manager`, `data-scientist` x `new york`, `san-francisco`, `london`... Plain text or Wellfound slugs both work. Every role is searched in every location.
- **Remote only** - each role's remote listing, with the locations remote applicants are accepted from.
- **Location only** - every startup job in a city.
- **Wellfound search URLs** - paste `/role/l/<role>/<location>`, `/role/r/<role>`, `/role/<role>` or `/location/<location>` pages.
- **Job URLs** - scrape specific job pages in full.
- **Deep paging** - up to 2000 jobs per search; the `SEARCHES` record tells the total on Wellfound and the page to continue from.
- **Deduplicated** - a job found by several searches, or also given as a job URL, is returned and billed once (it still counts toward each search's limit).

### Use cases

- **Job boards and aggregators** - fresh startup jobs with salary and equity ranges already parsed.
- **Compensation research** - salary and equity bands by role, city, company stage and size.
- **Recruiting and sales intelligence** - which startups are hiring for which roles right now, with their stage and badges.
- **Job alerts** - schedule the actor and compare `postedAt` with your last run.

### Input

| Field | Type | Default | Description |
|-------|------|---------|-------------|
| `roles` | array | - | Roles as text or slug (`software engineer`, `product-manager`). |
| `locations` | array | - | Locations as text or slug (`new york`, `london`). |
| `remoteOnly` | boolean | `false` | Search each role's remote listing (locations are not used then). |
| `searchUrls` | array | - | Wellfound job search URLs. |
| `jobUrls` | array | - | Wellfound job URLs (`https://wellfound.com/jobs/4787364-software-engineer`). |
| `maxResultsPerSearch` | integer | `50` | Jobs per role / location / search URL (1-2000). |
| `includeJobDetails` | boolean | `false` | Add each job's full job page under `details`. |
| `proxyCountry` | string | - | ISO-2 country to send requests from. |

A run with no roles, locations, search URLs or job URLs searches `software-engineer`.

#### Example input

```json
{
  "roles": ["data scientist", "product-manager"],
  "locations": ["new york", "london"],
  "maxResultsPerSearch": 100,
  "includeJobDetails": true
}
```

### Output

One dataset item per job. A search listing row (`source: "search"`, description shortened):

```json
{
  "id": "4787364",
  "title": "Software Engineer",
  "url": "https://wellfound.com/jobs/4787364-software-engineer",
  "primaryRole": "Software Engineer",
  "jobType": "full-time",
  "compensation": "$170k - $250k",
  "salary": {"min": 170000, "max": 250000, "currency": "USD"},
  "equity": null,
  "locations": ["New York City", "San Francisco"],
  "remote": false,
  "remotePolicy": "ONSITE",
  "acceptedRemoteLocations": [],
  "yearsExperienceMin": 4,
  "yearsExperienceMax": null,
  "postedAt": "2026-09-30T23:42:54Z",
  "description": "**About Chalk**\n\nChalk is building the data platform that powers the future of machine learning applications...",
  "company": {
    "name": "Chalk",
    "slug": "chalk-ai",
    "url": "https://wellfound.com/company/chalk-ai",
    "tagline": "Building machine learning infrastructure to answer the world's hardest questions",
    "companySize": "51-200",
    "stage": "Early Stage",
    "badges": ["Actively Hiring", "B2B", "Early Stage", "Top Investors"]
  },
  "source": "search",
  "search": {"role": "software-engineer", "location": null, "remote": false},
  "position": 1
}
```

With `includeJobDetails`, the row also has `details` - the job page (shortened):

```json
{
  "employmentType": "FULL_TIME",
  "datePosted": "2026-09-30T23:42:54Z",
  "industry": "Machine Learning and Computer Science",
  "salary": {"min": 170000, "max": 250000, "currency": "USD", "period": "YEAR"},
  "jobLocations": [{"city": "New York", "region": "New York", "country": "United States"}],
  "remotePolicy": "In office",
  "visaSponsorship": false,
  "relocation": true,
  "skills": ["Python", "C++", "Rust"],
  "hiringContact": null,
  "descriptionHtml": "<p><strong>About Chalk</strong></p>...",
  "company": {"name": "Chalk", "website": "https://chalk.ai/about", "founders": [{"name": "..."}]}
}
```

A job given in `jobUrls` is the job page itself with `source: "job"` and `input`.

The key-value store also holds:

- `SEARCHES` - per search: total jobs and companies on Wellfound, page count, jobs listed and delivered, pages fetched and `nextPage` to continue from.
- `ERRORS` - searches or job URLs that returned nothing (unknown role or location, removed job, blocked) with the reason. These are **not billed**.

### Pricing

**$1 per 1000 jobs** - a listing row, a row with job page details and a job URL cost the same. You pay only for jobs delivered; failed inputs are not charged.

### Notes

- A Wellfound listing page shows 20 startups with up to 3 matching jobs each, so `totalJobs` on Wellfound can be higher than the number of jobs a search can list.
- An unknown role or location (or a location Wellfound has no listing for with that role) ends in `ERRORS` with Wellfound's reason - use the role and city names Wellfound itself uses.
- If a job page cannot be opened (for example a job Wellfound took down after listing it), the listing row is still delivered with `details: null` and the reason in `detailsError`.

# Actor input Schema

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

Roles to search, as text or Wellfound slug: 'software engineer', 'product-manager', 'data-scientist', 'designer'. With Locations, every role is searched in every location. Empty runs use the example role only when Locations, Search URLs and Job URLs are empty too.

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

Locations, as text or Wellfound slug: 'new york', 'san-francisco', 'london', 'berlin', 'bangalore'. Without Roles, each location lists jobs of every role there.

## `remoteOnly` (type: `boolean`):

Search each role's remote listing. Wellfound lists remote jobs per role without a location, so Locations are not used when this is on.

## `searchUrls` (type: `array`):

Wellfound job search pages instead of (or besides) roles and locations: https://wellfound.com/role/l/software-engineer/san-francisco, /role/r/<role> (remote), /role/<role>, /location/<location>.

## `jobUrls` (type: `array`):

Wellfound job pages to scrape in full (https://wellfound.com/jobs/4787364-software-engineer, or '4787364-software-engineer'): description, salary with period, skills, visa sponsorship, relocation, remote policy, hiring contact, company funding and founders.

## `maxResultsPerSearch` (type: `integer`):

How many jobs to list for each role / location / search URL (1-2000). A Wellfound listing page holds 20 companies with up to 3 jobs each (usually 30-60 jobs). A job another search already returned counts here but is returned (and billed) once.

## `includeJobDetails` (type: `boolean`):

Also open every job found by a search and add its job page under `details`: skills, visa sponsorship, relocation, hiring contact, preferred timezones, salary period and the company's funding and founders. Same price per job; the run takes longer.

## `proxyCountry` (type: `string`):

Country the requests are sent from (ISO-2, e.g. 'US', 'DE'). Leave blank for the best default.

## Actor input object example

```json
{
  "roles": [
    "software-engineer"
  ],
  "remoteOnly": false,
  "maxResultsPerSearch": 50,
  "includeJobDetails": false
}
```

# Actor output Schema

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

One item per job, with `source` = search (listing row) or job (full job page)

## `searches` (type: `string`):

Per search: total jobs and companies on Wellfound, jobs collected, pages fetched and the page to continue from

## `errors` (type: `string`):

Searches or job URLs that returned nothing (unknown role / location, removed job, or blocked), with the reason (not billed)

# 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"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("scrapeunblocker/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"] }

# Run the Actor and wait for it to finish
run = client.actor("scrapeunblocker/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"
  ]
}' |
apify call scrapeunblocker/wellfound-jobs-scraper --silent --output-dataset

```

## MCP server setup

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