# Wellfound Jobs Scraper (Startup Jobs, Salary, Equity) (`praguedatalab/wellfound-jobs-scraper`) Actor

Wellfound (AngelList) startup jobs by role and city or remote: title, company, stage, size, badges, salary, equity, remote, locations, description, date. No proxy needed. $0.50 per 1,000.

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

## Pricing

$0.50 / 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?

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 — startup jobs with salary, equity and company stage

Scrape Wellfound startup jobs (ex-AngelList Talent) by role and city or remote, and get one clean row per job: title, company, company stage, size and badges (Top Investors, YC Funded…), salary range, equity range, job type, remote policy, locations, years of experience, full description and posting date. **$0.50 per 1,000 jobs.** No browser, no login, no proxy needed.

### Quick start

Minimal input:

```json
{
    "roles": ["software-engineer"],
    "location": ["san-francisco"],
    "maxResults": 30
}
```

Several roles and cities, filters, job pages for company website and HTML description:

```json
{
    "roles": ["software-engineer", "product-manager"],
    "location": ["london", "berlin"],
    "jobType": "fulltime",
    "salaryMin": 80000,
    "enrichDetail": true,
    "maxResults": 500
}
```

Remote jobs: `{"roles": ["data-scientist"], "remote": true}`. Or paste search URLs: `{"searchUrls": ["https://wellfound.com/role/l/product-manager/berlin"]}`.

**Compatible with the input of `blackfalcondata/wellfound-scraper`**, so you can switch by changing only the Actor ID: `query`, `roles`, `searchUrls`, `startUrls`, `location`, `excludeLocations`, `remote`, `jobType`, `experienceLevel`, `salaryMin`, `salaryMax`, `equityMin`, `visaSponsorship`, `includeCompanies`, `excludeCompanies`, `fromDate`, `toDate`, `maxAgeMinutes`, `maxResults`, `maxPages`, `enrichDetail`, `descriptionFormat`, `descriptionMaxLength`, `compact`, `excludeEmptyFields`, `proxyConfiguration` work as they are. Its output field names are kept too (`id`, `title`, `detailUrl`, `companyName`, `companySize`, `companyStage`, `companyBadges`, `compensation`, `salaryMin`, `salaryMax`, `salaryEquityMin`, `hasEquity`, `jobType`, `locationNames`, `remote`, `postedAt`, `atsSource`…). Notification fields (Telegram, Slack, Discord, WhatsApp, webhooks), radius search, incremental mode and company-only mode are ignored with a warning; use Apify schedules and integrations instead. `enrichEmails` is refused: this Actor returns company data only, never people's contact details.

### Sample output row

```json
{
    "id": "4787364",
    "title": "Software Engineer",
    "slug": "software-engineer",
    "detailUrl": "https://wellfound.com/jobs/4787364-software-engineer",
    "companyName": "Chalk",
    "companyId": "8887646",
    "companySlug": "chalk-ai",
    "companyUrl": "https://wellfound.com/company/chalk-ai",
    "companyLogo": "https://photos.wellfound.com/startups/i/8887646-f35c5c1d88595ca051fddbec6e486edd-medium_jpg.jpg?buster=1652299292",
    "companyTagline": "Building machine learning infrastructure to answer the world’s hardest questions",
    "companySize": "51-200",
    "companyStage": "Early Stage",
    "companyBadges": [
        "Actively Hiring",
        "Top 10% of responders",
        "Responds within a week",
        "B2B",
        "Top Investors"
    ],
    "companyWebsite": null,
    "industry": null,
    "compensation": "$170k – $250k",
    "salaryMin": 170000,
    "salaryMax": 250000,
    "salaryCurrency": "USD",
    "salaryPeriod": "YEAR",
    "salaryEquityMin": null,
    "salaryEquityMax": null,
    "hasEquity": null,
    "jobType": "fulltime",
    "primaryRoleTitle": "Software Engineer",
    "locationNames": [
        "New York City",
        "San Francisco"
    ],
    "remote": false,
    "remoteKind": "ONSITE",
    "wfhFlexible": false,
    "acceptedRemoteLocations": [],
    "locations": null,
    "yearsExperienceMin": 4,
    "yearsExperienceMax": null,
    "description": "About Chalk\n\nChalk is building the data platform that powers the future of machine learning applications. …",
    "descriptionText": "About Chalk\n\nChalk is building the data platform that powers the future of machine learning applications. …",
    "descriptionMarkdown": "**About Chalk**\n\nChalk is building the data platform that powers the future of machine learning applications. …",
    "descriptionHtml": null,
    "postedAt": "2026-09-30T23:42:54.000Z",
    "atsSource": null,
    "autoPosted": false,
    "searchRole": "software-engineer",
    "searchLocation": "san-francisco",
    "searchUrl": "https://wellfound.com/role/l/software-engineer/san-francisco",
    "remoteSearch": false,
    "scrapedAt": "2026-10-23T05:26:02.648Z"
}
```

With `enrichDetail` the row also gets `companyWebsite`, `industry`, `descriptionHtml` and `locations` (`[{"city": "San Francisco", "region": "California", "country": "United States"}]`).

### Input

| Field | Type | Description |
|---|---|---|
| `roles` | array | Wellfound role slugs, one search per role (and per location). Examples: `software-engineer`, `product-manager`, `data-scientist`, `product-designer`, `growth-marketer`, `sales-manager`. |
| `location` | array | Wellfound location slugs, e.g. `san-francisco`, `new-york`, `london`, `berlin`. Each role × location is one search. Leave empty for all locations. |
| `remote` | boolean | Search the remote job pages instead of a city. Locations are then ignored. |
| `query` | string | Free text searched as the Wellfound role category with the same name ("software engineer" → software-engineer). Field name of blackfalcondata/wellfound-scraper. |
| `searchUrls` | array | Wellfound search URLs pasted from the browser, e.g. `https://wellfound.com/role/l/product-manager/berlin` or `https://wellfound.com/role/r/data-scientist`. When set, roles, locations and remote are ignored. `startUrls` is accepted too. |
| `maxResults` | integer | Maximum number of jobs saved (you pay per job). 0 = no limit (capped at 20,000). `maxItems` is accepted too. |
| `maxPages` | integer | Safety bound: search pages read per role/location (about 40 jobs per page). |
| `jobType` | string | Keep only this employment type. |
| `experienceLevel` | string | Minimum years of experience required: entry 0–2, mid 2–5, senior 5–8, staff 8+. Jobs without the information are kept. |
| `salaryMin` | integer | Drop jobs whose top of range is below this yearly amount (in the job's currency). Jobs without salary are dropped when set. |
| `salaryMax` | integer | Drop jobs whose bottom of range is above this yearly amount. |
| `equityMin` | number | Drop jobs whose maximum equity grant is below this percent. Jobs without equity data are dropped when set. |
| `visaSponsorship` | boolean | true = only jobs whose description offers visa sponsorship; false = drop jobs that refuse it. Leave unset for no filter. |
| `includeCompanies` | array | Keep only jobs from companies whose name or Wellfound slug contains one of these (case-insensitive). |
| `excludeCompanies` | array | Drop jobs from companies whose name or slug contains one of these. |
| `excludeLocations` | array | Drop jobs whose locations contain one of these words, e.g. India. |
| `fromDate` | string | Only jobs posted on or after this date (YYYY-MM-DD or ISO 8601). |
| `toDate` | string | Only jobs posted on or before this date (YYYY-MM-DD or ISO 8601). |
| `maxAgeMinutes` | integer | Only jobs posted within the last N minutes. Handy for scheduled runs. |
| `enrichDetail` | boolean | Also open each job page for the company website, industry, exact salary, HTML description and structured locations. Slower (about 1.5 s per job), same price. |
| `descriptionFormat` | string | `all` keeps descriptionText, descriptionMarkdown and descriptionHtml (HTML needs job pages); the other values keep only `description` in that format. |
| `descriptionMaxLength` | integer | Truncate descriptions to this many characters. 0 = no truncation. |
| `compact` | boolean | Only id, title, companyName, detailUrl, locationNames, remote, compensation and postedAt. For AI agents. |
| `excludeEmptyFields` | boolean | Remove null, empty-string and empty-array fields from each row. |
| `proxyConfiguration` | object | Not needed: Wellfound answers from Apify's datacenter servers. Set a proxy only if your runs get blocked. |
| `maxItems` | integer | Alias of `maxResults`. |

### Output fields

| Field | Description |
|---|---|
| `id` | Wellfound job id (deduplication key). |
| `title` | Job title. |
| `slug` | Job slug in the Wellfound URL. |
| `detailUrl` | Job page on Wellfound. |
| `companyName` | Company name. |
| `companyId` | Wellfound company id. |
| `companySlug` | Company slug on Wellfound. |
| `companyUrl` | Company page on Wellfound. |
| `companyLogo` | Company logo URL. |
| `companyTagline` | One-line company pitch. |
| `companySize` | Employee range: 1-10, 11-50, 51-200, 201-500, 501-1000, 1001-5000, 5000+. |
| `companyStage` | Stage badge: Early Stage, Growth Stage, Scale Stage, Public Stage. |
| `companyBadges` | Other company badges, e.g. Top Investors, YC Funded, B2B, Growing fast, Valuation $1B+, Responds within a week. |
| `companyWebsite` | Company website (with enrichDetail). |
| `industry` | Company industry (with enrichDetail). |
| `compensation` | Compensation as shown on Wellfound, e.g. "$120k – $160k • 0.5% – 2.0%". |
| `salaryMin` | Bottom of the salary range, yearly, in salaryCurrency. |
| `salaryMax` | Top of the salary range, yearly, in salaryCurrency. |
| `salaryCurrency` | ISO currency code: USD, EUR, GBP, CAD, INR… |
| `salaryPeriod` | YEAR (Wellfound shows yearly salaries). |
| `salaryEquityMin` | Bottom of the equity range, percent. |
| `salaryEquityMax` | Top of the equity range, percent. |
| `hasEquity` | true when equity is offered, false for "No equity", null when not stated. |
| `jobType` | fulltime, parttime, contract, internship or cofounder. |
| `primaryRoleTitle` | Wellfound role category, e.g. Software Engineer. |
| `locationNames` | Office locations. |
| `remote` | true when remote work is possible. |
| `remoteKind` | ONSITE, REMOTE or ONSITE_OR_REMOTE. |
| `wfhFlexible` | Flexible work-from-home days. |
| `acceptedRemoteLocations` | Countries or regions accepted for remote hires. |
| `locations` | Structured locations (city, region, country), with enrichDetail. |
| `yearsExperienceMin` | Minimum years of experience required. |
| `yearsExperienceMax` | Maximum years of experience. |
| `description` | Job description in the chosen descriptionFormat (plain text for all). |
| `descriptionText` | Description as plain text (descriptionFormat all). |
| `descriptionMarkdown` | Description as Markdown (descriptionFormat all). |
| `descriptionHtml` | Description as HTML (descriptionFormat all, with enrichDetail). |
| `postedAt` | When the job went live, ISO 8601 UTC. |
| `atsSource` | Applicant tracking system the job is synced from (greenhouse, lever, ashby…), null when posted on Wellfound. |
| `autoPosted` | true when Wellfound imported the job automatically. |
| `searchRole` | Role slug of the search that found the job. |
| `searchLocation` | Location slug of the search, null for all locations or remote. |
| `searchUrl` | Search page that listed the job. |
| `remoteSearch` | true when found by a remote search. |
| `scrapedAt` | When the row was saved, ISO 8601 UTC. |

### Pricing

Pay per event: **$0.0005 per job saved** ($0.50 per 1,000), the same with or without `enrichDetail`. Duplicates and filtered-out jobs are not saved and not charged. Set `maxResults` (or a maximum cost per run) to control the total. No platform usage is added on top.

### Limits

- Wellfound search pages list companies with their highlighted jobs (about 40 jobs per page, up to the page count Wellfound shows). A company with many openings may show only its first jobs in a search; use narrower roles or locations to reach more.
- A free-text `query` is searched as the Wellfound role category with the same name. If no such category exists, the run says so; use a role slug instead.
- Requests are spaced (about 1.5 s) and sent one at a time. If Wellfound answers with a challenge page, the run stops cleanly with what it has and says so in the status message; retry later or set a proxy.
- Jobs and company descriptions come from Wellfound and belong to the companies that posted them. No recruiter or founder profiles are collected.

# Actor input Schema

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

Wellfound role slugs, one search per role (and per location). Examples: <code>software-engineer</code>, <code>product-manager</code>, <code>data-scientist</code>, <code>product-designer</code>, <code>growth-marketer</code>, <code>sales-manager</code>.

## `location` (type: `array`):

Wellfound location slugs, e.g. <code>san-francisco</code>, <code>new-york</code>, <code>london</code>, <code>berlin</code>. Each role × location is one search. Leave empty for all locations.

## `remote` (type: `boolean`):

Search the remote job pages instead of a city. Locations are then ignored.

## `query` (type: `string`):

Free text searched as the Wellfound role category with the same name ("software engineer" → software-engineer). Field name of blackfalcondata/wellfound-scraper.

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

Wellfound search URLs pasted from the browser, e.g. <code>https://wellfound.com/role/l/product-manager/berlin</code> or <code>https://wellfound.com/role/r/data-scientist</code>. When set, roles, locations and remote are ignored. <code>startUrls</code> is accepted too.

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

Maximum number of jobs saved (you pay per job). 0 = no limit (capped at 20,000). <code>maxItems</code> is accepted too.

## `maxPages` (type: `integer`):

Safety bound: search pages read per role/location (about 40 jobs per page).

## `jobType` (type: `string`):

Keep only this employment type.

## `experienceLevel` (type: `string`):

Minimum years of experience required: entry 0–2, mid 2–5, senior 5–8, staff 8+. Jobs without the information are kept.

## `salaryMin` (type: `integer`):

Drop jobs whose top of range is below this yearly amount (in the job's currency). Jobs without salary are dropped when set.

## `salaryMax` (type: `integer`):

Drop jobs whose bottom of range is above this yearly amount.

## `equityMin` (type: `number`):

Drop jobs whose maximum equity grant is below this percent. Jobs without equity data are dropped when set.

## `visaSponsorship` (type: `boolean`):

true = only jobs whose description offers visa sponsorship; false = drop jobs that refuse it. Leave unset for no filter.

## `includeCompanies` (type: `array`):

Keep only jobs from companies whose name or Wellfound slug contains one of these (case-insensitive).

## `excludeCompanies` (type: `array`):

Drop jobs from companies whose name or slug contains one of these.

## `excludeLocations` (type: `array`):

Drop jobs whose locations contain one of these words, e.g. India.

## `fromDate` (type: `string`):

Only jobs posted on or after this date (YYYY-MM-DD or ISO 8601).

## `toDate` (type: `string`):

Only jobs posted on or before this date (YYYY-MM-DD or ISO 8601).

## `maxAgeMinutes` (type: `integer`):

Only jobs posted within the last N minutes. Handy for scheduled runs.

## `enrichDetail` (type: `boolean`):

Also open each job page for the company website, industry, exact salary, HTML description and structured locations. Slower (about 1.5 s per job), same price.

## `descriptionFormat` (type: `string`):

<code>all</code> keeps descriptionText, descriptionMarkdown and descriptionHtml (HTML needs job pages); the other values keep only <code>description</code> in that format.

## `descriptionMaxLength` (type: `integer`):

Truncate descriptions to this many characters. 0 = no truncation.

## `compact` (type: `boolean`):

Only id, title, companyName, detailUrl, locationNames, remote, compensation and postedAt. For AI agents.

## `excludeEmptyFields` (type: `boolean`):

Remove null, empty-string and empty-array fields from each row.

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

Not needed: Wellfound answers from Apify's datacenter servers. Set a proxy only if your runs get blocked.

## Actor input object example

```json
{
  "roles": [
    "software-engineer"
  ],
  "location": [
    "san-francisco"
  ],
  "remote": false,
  "maxResults": 30,
  "maxPages": 10,
  "enrichDetail": false,
  "descriptionFormat": "all",
  "compact": false,
  "excludeEmptyFields": false,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# 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 = {
    "roles": [
        "software-engineer"
    ],
    "location": [
        "san-francisco"
    ],
    "maxResults": 30,
    "maxPages": 10,
    "proxyConfiguration": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("praguedatalab/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"],
    "location": ["san-francisco"],
    "maxResults": 30,
    "maxPages": 10,
    "proxyConfiguration": { "useApifyProxy": False },
}

# Run the Actor and wait for it to finish
run = client.actor("praguedatalab/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"
  ],
  "location": [
    "san-francisco"
  ],
  "maxResults": 30,
  "maxPages": 10,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}' |
apify call praguedatalab/wellfound-jobs-scraper --silent --output-dataset

```

## MCP server setup

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