# Wellfound Jobs Scraper (`nice_dev/wellfound-jobs-scraper`) Actor

Scrape startup jobs from Wellfound (ex-AngelList Talent): full description, salary and equity as numbers, remote, company, funding and visa. Export to JSON, CSV or Excel.

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

## Pricing

from $0.34 / 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.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

### 💼 What is Wellfound Jobs Scraper?

**Wellfound Jobs Scraper** extracts **startup jobs from [Wellfound](https://wellfound.com)** (ex-AngelList Talent): the **full job description**, the **salary AND the equity range split into numbers**, the job type, the location, remote setup, the hiring company with its size, stage, markets, amount raised and funding rounds, plus visa sponsorship, relocation and GPS coordinates.

Type a **job category** (`Software Engineer`), add a **location** if you want one, click **Start**, and download the jobs in JSON, CSV or Excel. No login, nothing to set up. A listing-only run reads about **1,800 jobs a minute**; with each job page opened, about **45 jobs a minute**.

### 📋 What data can you extract from Wellfound?

One item per job, 83 fields:

| Category | What you get |
| --- | --- |
| 💼 **Job** | title, category, link, apply link, job type (full-time, contract, internship, cofounder) — `Software Engineer` |
| 📝 **Full job ad** | the whole description, as text and as HTML — 4,800 characters on average |
| 💰 **Salary and equity** | the salary range and the equity range as numbers, with currency and period — `$120k – $200k • 0.01% – 0.15%` |
| 📍 **Location and remote** | city, region, country, GPS, remote or not, the countries a remote job accepts — `Austin, Texas` |
| 🎓 **Requirements and perks** | years of experience asked, visa sponsorship, relocation, recruiter recently active |
| 🏢 **Company** | name, website, logo, tagline, size, employees, stage, B2B or B2C, markets, industries, badges such as "Actively Hiring" |
| 💵 **Funding** | amount raised, in text and in dollars, and every funding round with its date — `Seed, $5.6M, Feb 2022` |
| 👥 **Founders** | name, role, years at the company and Wellfound profile of each founder |
| 🏷️ **Company page** | the company's own description, perks and benefits, culture photos, LinkedIn / X / Facebook / blog / Product Hunt links, open jobs in all and by role (option) |
| ✉️ **E-mails** | addresses published on the company's own website (option) |
| 🕒 **Dates and freshness** | publication date — what the date filters read — and how long the results page had been cached |

Every field, with an example, is listed in the **Output** section below.

The whole description, the compensation text, the equity, the job type, the date, the location and the company card come from the **results page**: they are filled whether or not **Extract job details** is on. The fields marked **detail** in the Output tab (`descriptionHtml`, exact salary figures, GPS, industries, company website, visa, relocation, recruiter activity, employees, markets, funding, founders, similar jobs) need it. `emails` and `emailSource` need **Find company e-mails** as well. The fields marked **company** need **Company page**, with or without **Extract job details**; in a list-only run it also fills the website, amount raised, markets and locations. A job URL pasted in **Start URLs** has no results page behind it: its job-page fields, title, salary and equity, date, company name, slug and Wellfound page are filled, as are the remote flag and policy and the "Actively Hiring" badge, read on the job page, while the Markdown description, job type, locations, the other badges and the rest of the company card stay empty (`null` or `[]`).

### ✅ Why use Wellfound Jobs Scraper?

- 📄 **The whole job ad, every time**: the full description (4,800 characters on average) comes with every job, at no extra request — most scrapers of this site return a title and a link.
- 💰 **Salary and equity as numbers**: `$120k – $200k • 0.01% – 0.15%` becomes `minSalary`, `maxSalary`, `salaryCurrency`, `salaryPeriod`, `minEquity` and `maxEquity`, ready to sort and filter.
- 🏢 **The company with the job**: size, stage, B2B/B2C, markets, amount raised, funding rounds, website, founders — and, with **Company page**, its description, perks, social links and open jobs — without a second product to run.
- ⏱️ **Freshness you can check**: `listPageCacheAgeSeconds` says how long the results page had been served from cache when it was read, instead of promising an hourly watch.
- 🧩 **Nothing missed, nothing twice**: pagination is automatic, every page of a search is read, each job is returned once — no 500-job ceiling.
- 🔔 **Monitoring built in**: tick **Only new jobs**, schedule the Actor, and each run returns (and charges) only what it has never delivered before.
- 🔌 API, scheduling, monitoring, integrations (Make, Zapier, n8n, Google Sheets…) and JSON/CSV/Excel export via the Apify platform.

### 🚀 How to scrape Wellfound

1. Create a free Apify account.
2. Open **Wellfound Jobs Scraper** and type a **Job category** (e.g. `Software Engineer`) — the categories Wellfound itself browses by.
3. Add a **Location** (`San Francisco`, `London`, `India`), or tick **Remote jobs only**. You can also paste your own Wellfound URLs into **Start URLs**: `/role/…`, `/role/l/…`, `/role/r/…`, `/location/…`, `/remote`, or single job pages.
4. Set **Max jobs** (20 in the form to try it out, 100 when an API call leaves it out, 0 = no limit) — and **Max jobs per search** when you run several searches — then click **Start**.
5. Download the dataset in JSON, CSV, Excel or via API.

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

This Actor uses **pay per event** pricing: **$0.40 per 1,000 jobs**, job pages included — plus **$0.0011 per run start** at the Actor's default memory (11 cents per 100 runs; the platform counts that event once per gigabyte, so a run you give more memory pays proportionally more). Higher Apify plans pay less per job: $0.38 (Bronze), $0.36 (Silver) and $0.34 (Gold and above) per 1,000. **Find company e-mails** costs nothing more. **Company page** costs $1.00 per 1,000 companies ($0.90 Bronze, $0.85 Silver, $0.80 Gold and above), each company charged once per run however many of its jobs you get, plus $0.005 per run that uses it; the run takes 1 GB of memory instead of 256 MB (still one run start). Example: 20,000 jobs ≈ $8; a daily monitor of 200 new jobs ≈ $0.08 a day. The filters are applied by the Actor on every job it reads, kept or not: $0.025 per 1,000 job cards checked by a filter (`filter-check`; $0.023 Bronze, $0.021 Silver, $0.020 Gold and above) and $0.20 per 1,000 job pages read for **Industries** or **Visa sponsorship only** (`detail-filter-check`; $0.19 Bronze, $0.18 Silver, $0.17 Gold and above) — a search that finds nothing pays for what it read (8,000 jobs checked ≈ $0.20). Platform usage (compute, proxy) is included in the price.

### ⚙️ Input

```json
{
    "query": "Software Engineer",
    "location": "San Francisco",
    "maxItems": 200,
    "extractDetails": true
}
```

Several searches, a cap per search, a keyword filter, only recent jobs, only the ones not delivered before:

```json
{
    "searchQueries": ["Software Engineer", "Data Scientist"],
    "locations": ["San Francisco", "New York"],
    "maxItemsPerQuery": 50,
    "includeKeywords": ["python", "rust"],
    "minSalary": 150000,
    "postedAfter": "7 days",
    "onlyNew": true,
    "stateKey": "us-engineers"
}
```

Or with your own URLs:

```json
{
    "startUrls": [
        { "url": "https://wellfound.com/role/r/designer" },
        { "url": "https://wellfound.com/jobs/4716782-software-engineer" }
    ],
    "maxItems": 500
}
```

| Field                                       | Notes                                                                                                                                                                       |
| ------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `query`, `searchQueries`                    | The Wellfound job CATEGORY, as the site browses by (`Software Engineer`, `Product Manager`). Not a free-text search: Wellfound offers none to visitors. Ignored when `startUrls` is set. |
| `location`, `locations`                     | City, region or country as Wellfound names it (`San Francisco`, `London`, `India`). Every category is searched in every location (max 500 searches per run).                 |
| `remoteOnly`                                | Browse the remote pages instead of the on-site ones. Cannot be combined with a location: those pages carry no place.                                                        |
| `startUrls`                                 | Wellfound results pages (pagination automatic) or single job pages.                                                                                                         |
| `extractDetails`                            | Open each job page for the exact salary, GPS, industry, company website, visa, relocation, funding and founders (default on). Off = about 40× faster, same price.            |
| `enrichEmails`                              | Read the company's own website (up to 3 pages, once per company) for its e-mail addresses. Wellfound publishes none. Needs `extractDetails`.                                 |
| `enrichCompany`                             | Read each company's Wellfound page once per run: description, perks, culture photos, social links, open jobs. Works in list-only runs too. Takes 1 GB of memory (set automatically). |
| `maxItems`                                  | Stop after this many jobs for the whole run (0 = unlimited).                                                                                                                |
| `maxItemsPerQuery`                          | Cap for EACH search (category × location, or search URL). 0 = no per-search cap.                                                                                            |
| `maxPages`                                  | Stop each search after this many results pages (about 40 jobs a page). 0 = every page the site serves.                                                                      |
| `includeKeywords`, `excludeKeywords`        | Keep, or drop, the jobs whose title or description holds one of these words (case and accents ignored). This is how you search by keyword here.                              |
| `jobTypes`                                  | `full-time`, `part-time`, `contract`, `internship`, `cofounder`.                                                                                                            |
| `minSalary`, `maxSalary`, `includeNoSalary` | Salary range to overlap, and whether the jobs showing no salary are kept (8 % of them).                                                                                     |
| `minEquity`, `maxYearsExperience`           | Equity floor in percent; jobs asking for at most this many years (jobs stating none are kept).                                                                              |
| `companySizes`, `companyStages`, `companyTypes`, `activelyHiringOnly` | Employee bucket, stage label (`Early Stage`), `B2B` / `B2C`, and Wellfound's "Actively Hiring" badge.                                             |
| `includeCompanies`, `excludeCompanies`      | Company names or Wellfound slugs (`Boom`, `boom-app`).                                                                                                                      |
| `industries`, `visaSponsorshipOnly`         | Company industry, and only the jobs whose page states that visa sponsorship is available. Both need `extractDetails`.                                                       |
| `postedAfter`, `postedBefore`               | Publication date range: `2026-09-01`, or a period before now (`7 days`, `2 weeks`, `1 month`, `24 hours`).                                                                   |
| `onlyNew`, `stateKey`, `resetState`         | Monitoring: only the jobs never delivered under this memory key; `resetState` forgets the memory.                                                                           |
| Advanced                                    | `proxyConfiguration` (Apify proxy by default, included in the price; the residential proxy is not available), `maxConcurrency`, `maxRequestsPerMinute`, `maxRequestRetries`, `debugLog`. |

### 📦 Output

One item, shortened to its first fields (a real item carries all 83):

```json
{
    "id": "4716782",
    "url": "https://wellfound.com/jobs/4716782-software-engineer",
    "applyUrl": "https://wellfound.com/jobs/4716782-software-engineer",
    "slug": "software-engineer",
    "title": "Software Engineer",
    "primaryRoleTitle": "Software Engineer",
    "description": "# **Software Engineer**\n\nWe hire software engineers across levels under a single posting...",
    "compensation": "$120k – $200k • 0.01% – 0.15%",
    "minSalary": 120000,
    "maxSalary": 200000,
    "salaryCurrency": "USD",
    "salaryPeriod": "YEAR",
    "salarySource": "card",
    "hasEquity": true,
    "minEquity": 0.01,
    "maxEquity": 0.15,
    "jobType": "full-time",
    "publishedAt": "2026-09-15T00:00:52.000Z",
    "liveStartAt": 1789430452,
    "locationNames": ["Austin"],
    "remote": false,
    "acceptedRemoteLocationNames": [],
    "atsProvider": "Ashby",
    "autoPosted": false,
    "visaSponsorship": "Not Available",
    "relocation": "Not Allowed",
    "companyName": "Boom",
    "companySlug": "boom-app",
    "companyWebsite": "https://boompay.app",
    "companySizeLabel": "11-50",
    "companyStage": "Early Stage",
    "companyBusinessType": "B2C",
    "companyActivelyHiring": true,
    "companyGrowingFast": true,
    "companyBadges": [{ "id": "ACTIVELY_HIRING", "label": "Actively Hiring", "tooltip": "Actively processing applications" }],
    "companyLocationNames": ["Austin"],
    "founders": [
        {
            "name": "Rob Whiting",
            "role": "Co-founder",
            "tenure": "6 years",
            "location": "Austin",
            "profileUrl": "https://wellfound.com/p/rob-whiting"
        }
    ],
    "similarJobIds": ["2776321", "2777056"],
    "companyEmployees": "11-50",
    "companyMarkets": ["Real Estate", "Property Management", "Fin Tech"],
    "industries": ["Real Estate", "Property Management", "Fin Tech", "Financial Technology"],
    "companyTotalRaised": "$5.6M",
    "companyTotalRaisedUsd": 5600000,
    "companyFundingRounds": [{ "type": "Seed", "amount": "$5600000", "date": "Feb 2022" }],
    "emails": [],
    "searchQuery": "software-engineer",
    "searchLocation": "austin",
    "listPageCacheAgeSeconds": 8539,
    "source": "wellfound",
    "scrapedAt": "2026-09-20T12:00:00.000Z"
}
```

You can download the dataset in various formats such as JSON, HTML, CSV or Excel.

#### All 83 fields

| Fields | Example                                                                                 |
| -------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------- |
| `id`, `url`, `applyUrl`, `slug`                                                                | `4716782`, `https://wellfound.com/jobs/4716782-software-engineer`, same, `software-engineer` |
| `title`, `primaryRoleTitle`                                                                    | `Software Engineer`, `Software Engineer`                                                  |
| `description`, `descriptionHtml`                                                               | the whole job ad (Markdown), the same as HTML                                             |
| `compensation`, `minSalary`, `maxSalary`, `salaryCurrency`, `salaryPeriod`, `salarySource`     | `$120k – $200k • 0.01% – 0.15%`, `120000`, `200000`, `USD`, `YEAR`, `card`                |
| `hasEquity`, `minEquity`, `maxEquity`                                                          | `true`, `0.01`, `0.15` (percent)                                                          |
| `jobType`, `employmentType`                                                                    | `full-time`, `FULL_TIME`                                                                  |
| `publishedAt`, `liveStartAt`                                                                   | `2026-09-15T00:00:52.000Z` (what the date filters read), `1789430452`                     |
| `locationNames`, `remote`, `remoteConfig`, `acceptedRemoteLocationNames`                       | `["Austin"]`, `false`, `In office - WFH flexibility`, `["United States"]`                 |
| `minYearsExperience`, `maxYearsExperience`                                                     | `3`, `7`                                                                                  |
| `atsSource`, `atsProvider`, `autoPosted`, `directApply`                                        | `AtsIntegration::Ashby::Listing`, `Ashby`, `false`, `true`                                |
| `visaSponsorship`, `relocation`, `recruiterRecentlyActive`                                     | `Not Available`, `Not Allowed`, `true`                                                    |
| `latitude`, `longitude`, `addressLocality`, `addressRegion`, `addressCountry`                  | `30.2672`, `-97.7431`, `Austin`, `Texas`, `United States`                                 |
| `companyId`, `companyName`, `companySlug`, `companyUrl`, `companyWebsite`, `companyLogoUrl`    | `7775773`, `Boom`, `boom-app`, its Wellfound page, `https://boompay.app`, its logo        |
| `companyTagline`, `companySize`, `companySizeLabel`, `companyEmployees`                        | `Modern rental financial services`, `SIZE_11_50`, `11-50`, `11-50`                        |
| `companyStage`, `companyBusinessType`, `companyActivelyHiring`, `companyGrowingFast`, `companyBadges` | `Early Stage`, `B2C`, `true`, `true`, every badge with its tooltip                 |
| `companyLocationNames`, `companyLatitude`, `companyLongitude`                                  | `["Austin"]`, `30.2672`, `-97.7431`                                                       |
| `companyMarkets`, `industries`                                                                 | `["Real Estate", "Fin Tech"]`, `["Real Estate", "Property Management"]`                   |
| `companyTotalRaised`, `companyTotalRaisedUsd`, `companyFundingRounds`                          | `$5.6M`, `5600000`, `[{ "type": "Seed", "amount": "$5600000", "date": "Feb 2022" }]`      |
| `founders`, `similarJobIds`                                                                    | name, role, years and Wellfound profile of each founder; ids of the jobs shown as similar |
| `companyDescription`, `companyPerks`, `companyCulturePhotos`                                   | the company's own presentation, `[{ "category": "healthcare", "title": "Healthcare Benefits", … }]`, photo URLs (company) |
| `companyLinkedinUrl`, `companyTwitterUrl`, `companyFacebookUrl`, `companyBlogUrl`, `companyProductHuntUrl` | links of the company page, `null` when it has none (company)                     |
| `companyOpenJobsCount`, `companyOpenJobsByRole`, `companyPageRead`                             | `8`, `[{ "role": "Engineering", "count": 2 }]`, `true` (read) / `false` (asked, not read) / `null` (not asked) |
| `emails`, `emailSource`                                                                        | addresses found on the company's own website, and the page they were read on              |
| `searchQuery`, `searchLocation`, `searchUrl`                                                   | `software-engineer`, `austin`, the results page it was found on                           |
| `listPageCacheAgeSeconds`, `source`, `scrapedAt`                                               | `8539` (how long the results page had been cached), `wellfound`, ISO timestamp            |

### 💡 Tips

#### How to get more results

Set `maxItems` to `0`. Wellfound serves every page of a search — a category like `Software Engineer` carries about 5,000 jobs over 91 pages, `/remote` about 12,000 — so a broad category with no cap returns the lot. To cover more ground, list several categories in `searchQueries` and several places in `locations`: the Actor runs one search per pair and saves a job found twice only once.

#### How to reduce costs

The price is per job, so the levers are `maxItems`, `maxItemsPerQuery`, `maxPages`, the filters (a filtered-out job is not saved and does not count in `maxItems`; each job checked costs its small filter fee, see Pricing) and `onlyNew` for recurring runs. Turning `extractDetails` off makes runs about 40× faster (one request per results page of about 40 jobs instead of one per job) but does not change the price. `enrichEmails` adds nothing to the price; `enrichCompany` does (per company and per run), and a list-only run with it reads one company page per company. When the run's maximum cost can pay for no more jobs, it stops, and every job it saved is paid for.

#### Searching by keyword on a site that has no search

Wellfound gives visitors no keyword search — its own search sits behind a login. The Actor therefore browses the site's **categories** (`query`) and **places** (`location`), then filters on words with `includeKeywords` / `excludeKeywords`, which read the title AND the full description. Every scraper of this site works that way; this one says so instead of pretending to search.

#### How fresh is a row, really

Wellfound serves its results pages from a cache. `listPageCacheAgeSeconds` is the age of the page the job was read on, in seconds: `0` means it was read at the source, and ages of up to 21 hours have been measured on the most popular pages. Deeper pages are almost always read at the source. Use the field to know what a row is worth instead of trusting a promise of hourly freshness — and note that the site does not sort by date, so a run looking for recent jobs reads every page of its searches.

#### Several searches in one run

Fill `searchQueries` and / or `locations`: the Actor runs one search per category × place (3 categories × 4 cities = 12 searches, up to 500 per run). The single `query` and `location` fields still work and are added to the lists. A job found by several searches is saved — and charged — once. Set `maxItemsPerQuery` to give every search its own cap: without it the first searches can use up the whole `maxItems` budget. You can also paste several search URLs into `startUrls`: each one is a search of its own, with the same cap.

#### Monitoring: only the new jobs

Tick **Only new jobs** (`onlyNew`) and schedule the Actor. The first run returns everything; each later run skips the jobs already delivered: they are not saved, not charged, and their page is not even opened. A job re-posted under the same Wellfound id is not delivered twice either. The memory lives in a named key-value store of your account (`wellfound-jobs-scraper-seen`, up to 150,000 jobs per key) and is only updated with jobs that really reached the dataset, so a failed run never hides anything. Give each schedule its own `stateKey` (two schedules sharing a key would hide each other's jobs), and tick `resetState` once to start over. Because Wellfound does not sort by date, a monitoring run still reads every page of its searches — it just stops paying for what it already had. For the same reason, a capped run (`maxItems`) followed by another one returns the next jobs never delivered, old or new: add `postedAfter` (for example `2 days`) to keep only the recent ones.

#### Filter by publication date

`postedAfter` and `postedBefore` take a date (`2026-09-01`, the whole day is included, UTC) or a period before now (`7 days`, `2 weeks`, `1 month`; via the API also `24 hours` or a full ISO date-time). The filter reads `publishedAt`, which every Wellfound job carries; a job without a publication date is dropped as soon as a date bound is set. A filtered-out job is not saved and does not count in `maxItems`: it costs only its filter fee (see Pricing); the run summary tells how many were filtered.

### 🔌 Integrations and API

Call the Actor via the Apify API, the JavaScript or Python clients, or connect it with integrations and webhooks (Make, Zapier, n8n, Google Sheets, Slack, Airtable…). The dataset can be fetched as JSON or CSV from any tool.

### 🤖 Use with AI agents (MCP)

AI agents (Claude, ChatGPT, Cursor…) can find and run this Actor through the [Apify MCP server](https://mcp.apify.com), billed to their Apify account like any run. It returns one item per Wellfound job. Actor id: `nice_dev/wellfound-jobs-scraper`; MCP server with this Actor only: `https://mcp.apify.com/?tools=fetch-actor-details,nice_dev/wellfound-jobs-scraper`.

Smallest input, for a cheap first call:

```json
{
    "query": "Software Engineer",
    "maxItems": 10
}
```

Key output fields: `url`, `title`, `companyName`, `minSalary`, `maxSalary`, `salaryCurrency`, `locationNames` and `description` (with `extractDetails`).

Cost: $0.40 per 1,000 jobs plus $0.0011 per run start ($0.34 per 1,000 on the Gold plan). The company page option and the filters cost extra, see the pricing section above. Cap each call with `maxItems` and, through the API, with the run option `maxTotalChargeUsd`.

### ❓ FAQ

#### Is it legal to scrape Wellfound?

The Actor only reads what Wellfound shows publicly to any anonymous visitor. It logs in to nothing. Job ads and company profiles are professional information; the founders Wellfound publishes on a job page are named people, and personal data is protected by GDPR: do not store it without a legitimate reason. You are responsible for using the data in compliance with Wellfound's Terms of Use and applicable law. This Actor is not affiliated with Wellfound or AngelList.

#### Does it need a login or a proxy?

No login. The proxy is included in the price: leave the default setting (the residential proxy is not available). A request the site turns away is retried at once on a new proxy session, up to 10 times on top of the retries (without a proxy, after a pause of 5 seconds, doubled at each retry up to 150 seconds).

Now and then Wellfound's Cloudflare check turns the platform's IPs away. A run with 1 GB of memory or more (a **Company page** run has it) then passes the check on the page that was refused and goes on from its own connection. At the default 256 MB the run keeps retrying on new proxy sessions, and if it still fails, its last message says so: run it again, or give it 1 GB (Run options → Memory; the run start is charged per GB). A run that is never turned away costs nothing more.

#### Is the data safe to open in Excel or to show on a web page?

Titles and descriptions are the companies' own words, copied as they are. A text can begin with `-`, `+`, `=` or `@` (a title such as `-20% equity`): Excel and Google Sheets may read such a cell of a CSV file as a formula or as a number. The Actor leaves the text as it is, so that the JSON and the API give the real value: when you open a CSV, import these columns as text. Every URL field (`url`, `applyUrl`, `companyUrl`, `companyWebsite`, `companyLogoUrl`, the founders' profiles) holds an `http(s)` URL or `null`, never a `javascript:` or `data:` value. `descriptionHtml` is the company's own HTML and is not sanitized: escape it like any text written by a stranger before putting it on a page.

#### Known limitations

- Wellfound has no keyword search for visitors and no sort at all: `includeKeywords` and the date filters are applied to the jobs the categories and places return, so a run looking for a rare word reads whole searches.
- **Company page** reads each company's Wellfound page once per run, from the run's own connection whatever the proxy setting. A company page shows at most its first jobs: to get all of a company's jobs, search its categories and filter with `includeCompanies`. A job URL pasted in **Start URLs** gets its company page too: the company is read from the job page. When the page cannot be opened, the jobs are still delivered, with `companyPageRead: false` and the company fields empty, and that company is not charged.
- `remoteOnly` and `location` cannot be combined: the site's remote pages carry no place.
- `onlyNew` remembers job ids, not their content: a job whose description changed is not returned again.
- Two runs sharing the same `stateKey` at the same time may both return the same new job.

**A run the platform stops without warning** (out of memory, run timeout)

- Resurrect it: it goes on from where it stood at most a minute before the stop. What it had read since is read again, and the jobs already saved are skipped: none is delivered or charged twice, and `maxItems` still counts them.
- With `onlyNew`, the memory is saved once a minute: resurrect the stopped run and the jobs it had saved meanwhile join the memory; leave it stopped for good, and the next run may return up to a minute of them once more.

#### Something doesn't work?

The last line of the log counts the jobs saved, filtered out and no longer on Wellfound (taken down while the run was reading them), and the requests that failed after every retry. Those requests and the removed jobs are listed, with the reason, in the `FAILED_REQUESTS` record of the run's key-value store. A run that saved nothing and had failed requests fails, and its last message gives the cause (a search URL that does not exist says so, instead of "run it again"). A run that saved some jobs fails too when at least as many requests failed for good as were read (page 1 read, the next pages, the job pages or the company pages blocked): a green run with a short dataset would hide the outage. One failed request among many is only a warning.

If Wellfound changes its pages, you are told instead of paying for blank rows. A results page that counts jobs but gives none the Actor can read is an error (listed in `FAILED_REQUESTS`), never a quiet "No jobs found". So is a results page whose jobs all lack the salary line, the remote flag, the locations or the required experience (Wellfound sends them on every job, empty when a job has none): nothing is saved or charged. If the first 20 jobs read all lack their title, publication date, description, job type or company name, the run saves nothing more, stops and fails, and its last message names the missing field: at most those first jobs are charged. A job that `postedAfter` / `postedBefore` drops because it has no date at all counts among those 20.

### 🛟 Support

Open an issue in the **Issues** tab with a link to your run: the run log and the `FAILED_REQUESTS` record of the key-value store show exactly which URLs failed and why.

# Actor input Schema

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

Wellfound search URLs (`https://wellfound.com/role/software-engineer`, `/role/l/<role>/<city>`, `/role/r/<role>`, `/location/<city>`, `/remote`) or single job URLs (`https://wellfound.com/jobs/<id>-<slug>`). Pagination is automatic. When this list is not empty, the search fields below (job categories, locations) are ignored; filters, caps and monitoring still apply. Max 1 000 URLs.

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

Wellfound job category, as shown on the site (e.g. `Software Engineer`, `Product Manager`, `Data Scientist`). It is the site's own browse axis, not a free-text search: Wellfound has no keyword search for visitors. To filter on words, use **Must contain keywords** below.

## `searchQueries` (type: `array`):

Several categories in one run: one search per category (times each location below). Added to **Job category**; a job found by several searches is saved once.

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

City, region or country as named on Wellfound (e.g. `San Francisco`, `London`, `India`, `United States`). Empty = everywhere.

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

Several locations in one run: every category is searched in every location (3 categories × 4 locations = 12 searches, max 500). Added to **Location**.

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

Browse Wellfound's remote pages instead of the on-site ones (`/role/r/<category>`, or `/remote` when no category is given).

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

Maximum number of jobs to save for the whole run (after deduplication and filters). 0 = no limit — Wellfound serves every page of a search, so a category like `Software Engineer` can return about 5 000 jobs.

## `maxItemsPerQuery` (type: `integer`):

Cap for EACH search (category × location, or search URL), so that the first search cannot use up the whole **Max jobs** budget. 0 = no per-search cap.

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

Stop each search after this many result pages (about 40 jobs per page). 0 = every page the site serves. Use it to cap the number of requests rather than the number of results.

## `extractDetails` (type: `boolean`):

Open each job page (1 extra request per job) for: exact salary range and currency, GPS coordinates, industry, company website, visa sponsorship, relocation, recruiter activity, company size, markets, amount raised, funding rounds, founders, and the HTML description. Turn it OFF for a run about 40× faster (one request per result page of about 40 jobs), at the same price per job: the full description, the salary text and the equity are already on the result page.

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

Visit the company's own website (up to 3 pages, once per company and per run) and collect the e-mail addresses published there. Wellfound itself publishes no e-mail. Requires **Extract job details** (the company website is read from the job page).

## `enrichCompany` (type: `boolean`):

Read each company's Wellfound page once per run and add: its long description, perks and benefits, culture photos, LinkedIn / X / Facebook / blog / Product Hunt links, and how many jobs it has open, by role. Works with or without **Extract job details**, and also fills website, amount raised, markets and locations in list-only runs. The run takes 1 GB of memory instead of 256 MB — set automatically when this box is ticked. Charged per company and once per run (see Pricing).

## `includeKeywords` (type: `array`):

Keep only the jobs whose title or description contains at least one of these words (case and accents ignored). This is how you search by keyword on Wellfound: the site offers no keyword search to visitors.

## `excludeKeywords` (type: `array`):

Drop the jobs whose title or description contains one of these words (case and accents ignored).

## `jobTypes` (type: `array`):

Keep only these types. Empty = all. Measured on 238 jobs: full-time 228, internship 5, cofounder 3, contract 2.

## `minSalary` (type: `integer`):

Keep only the jobs whose salary range reaches at least this amount, in the currency Wellfound shows (mostly USD per year). Read from the compensation text of the result page, so it works without **Extract job details**.

## `maxSalary` (type: `integer`):

Keep only the jobs whose salary range starts at or below this amount.

## `includeNoSalary` (type: `boolean`):

Keep the jobs that show no salary when a salary filter is set. Measured: 92 % of jobs show a compensation, 8 % do not.

## `minEquity` (type: `number`):

Keep only the jobs whose equity range reaches at least this percentage (e.g. `0.1` for 0.1 %). Read from the same compensation text.

## `maxYearsExperience` (type: `integer`):

Keep only the jobs asking for at most this many years. Jobs that state no experience requirement are kept (Wellfound shows it on 28 % of jobs only).

## `companySizes` (type: `array`):

Keep only the jobs of companies of these sizes (number of employees, as Wellfound groups them). Empty = all.

## `companyStages` (type: `array`):

Keep only the jobs of companies at these stages, as written on the company badge (e.g. `Early Stage`, `Growth Stage`). Empty = all. Case ignored.

## `companyTypes` (type: `array`):

Keep only B2B and/or B2C companies, as Wellfound tags them. Empty = all.

## `activelyHiringOnly` (type: `boolean`):

Keep only the jobs of companies carrying Wellfound's "Actively Hiring" badge (the site's own sign that applications are being processed).

## `visaSponsorshipOnly` (type: `boolean`):

Keep only the jobs whose page states that visa sponsorship is available. Requires **Extract job details**: visa sponsorship is on the job page, not on the result page.

## `industries` (type: `array`):

Keep only the jobs whose company belongs to one of these industries (e.g. `Fin Tech`, `Real Estate`). Requires **Extract job details**: the industry is on the job page, not on the result page. Case ignored, partial match.

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

Keep only the jobs of these companies. Company name or Wellfound slug (e.g. `Boom` or `boom-app`). Case ignored.

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

Drop the jobs of these companies. Company name or Wellfound slug. Case ignored. Applied after **Only these companies**.

## `postedAfter` (type: `string`):

Only jobs published on or after this date: `2026-09-01`, or a period before now such as `7 days`, `2 weeks`, `1 month` (API: `24 hours` and full ISO date-times work too). Reads the job's `publishedAt` (Wellfound's `liveStartAt`), present on 100 % of jobs. Note: Wellfound does not sort by date, so a recent-jobs run still reads every page of the search.

## `postedBefore` (type: `string`):

Only jobs published on or before this date (the whole day is included), or older than a period such as `30 days`.

## `onlyNew` (type: `boolean`):

Skip the jobs that a previous run (same **Memory key**) already delivered: they are not saved and not charged, and their page is not even opened. A job re-posted under the same Wellfound id is therefore not delivered twice. First run = everything is new.

## `stateKey` (type: `string`):

Name of the memory used by **Only new jobs**. Give each schedule / task its own key (e.g. `sf-engineers`) so that they do not share their memory. Letters, digits, `-` and `_`.

## `resetState` (type: `boolean`):

Forget everything remembered under this **Memory key** before the run: this run returns (and charges) every job again. Untick it afterwards.

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

Apify Proxy or your own proxies. Keep the default: it is included in the price. The residential Apify proxy is not available in this Actor.

## `maxConcurrency` (type: `integer`):

Maximum number of requests processed in parallel. The default is 1: with the rate below it makes one request every 1.33 seconds, a pace this site serves without refusing. Raise it only when you route the run through several IPs.

## `maxRequestsPerMinute` (type: `integer`):

Global request rate. The default (45 = 0.75 request per second) stays under the ceiling measured on Wellfound, per IP: about 0.8 request per second can be held for good, while 1 request per second triggered HTTP 429 after about 2 minutes, and then the whole site refuses for about 5 minutes. Raise it only if you route the run through many IPs.

## `maxRequestRetries` (type: `integer`):

Retries per request before it is marked as failed. Behind a proxy, a request the site turns away is also retried on a new proxy session up to 10 times without using up these retries.

## `debugLog` (type: `boolean`):

Include debug messages in the run log.

## Actor input object example

```json
{
  "startUrls": [],
  "query": "Software Engineer",
  "searchQueries": [],
  "locations": [],
  "remoteOnly": false,
  "maxItems": 20,
  "maxItemsPerQuery": 0,
  "maxPages": 0,
  "extractDetails": true,
  "enrichEmails": false,
  "enrichCompany": false,
  "includeKeywords": [],
  "excludeKeywords": [],
  "jobTypes": [],
  "includeNoSalary": true,
  "companySizes": [],
  "companyStages": [],
  "companyTypes": [],
  "activelyHiringOnly": false,
  "visaSponsorshipOnly": false,
  "industries": [],
  "includeCompanies": [],
  "excludeCompanies": [],
  "onlyNew": false,
  "stateKey": "default",
  "resetState": false,
  "proxyConfiguration": {
    "useApifyProxy": true
  },
  "maxConcurrency": 1,
  "maxRequestsPerMinute": 45,
  "maxRequestRetries": 5,
  "debugLog": 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 = {
    "query": "Software Engineer",
    "maxItems": 20,
    "extractDetails": true,
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("nice_dev/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 = {
    "query": "Software Engineer",
    "maxItems": 20,
    "extractDetails": True,
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("nice_dev/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 '{
  "query": "Software Engineer",
  "maxItems": 20,
  "extractDetails": true,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call nice_dev/wellfound-jobs-scraper --silent --output-dataset

```

## MCP server setup

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