# Wellfound Jobs Scraper — Startup Salary, Equity, Visa & Funding (`yugenox/wellfound-startup-jobs-scraper`) Actor

Scrape startup jobs from Wellfound (AngelList Talent) by role, location or company — salary and equity as numbers, remote policy, posting date, company stage, YC and valuation badges, Glassdoor ratings, visa sponsorship and relocation. No login.

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

## Pricing

from $1.50 / 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 Startup Jobs Scraper

Scrape startup jobs from **Wellfound** (formerly AngelList Talent) by role and location. You get **salary and equity as numbers**, remote policy, posting date, job type and full description for each job. Each row also carries the company's **stage, size, Y Combinator / top-investor / $1B+ valuation badges, Glassdoor ratings and typical response time**. Optionally add **visa sponsorship and relocation** per job, or **every open job and the funding raised** per company.

No Wellfound account or login needed. Results are fetched fresh on every run. **Your Apify plan should include residential proxies**: without them the run falls back to Apify's slower unblocker proxy (no job details), and if your plan has neither it stops within seconds at no charge and tells you what to enable.

### What you can scrape

- **Any role in any location**: `software-engineer` in `san-francisco`, `product-manager` in `new-york`, `data-scientist` in `london`…
- **Remote jobs**: put `remote` as the location.
- **Everything in a city or country**: a location with no role, e.g. `toronto` or `united-states`.
- **Any Wellfound URL**: role pages, role + location pages, remote role pages, location pages, single job pages, company pages.
- **Whole companies**: every open job of `checkr`, `mercor`, … plus funding, website, LinkedIn, X and markets.

### Output fields

| Group | Fields |
|---|---|
| Job | `jobId`, `title`, `jobUrl`, `postedAt`, `jobType`, `primaryRole`, `description`, `yearsExperienceMin`, `atsSource` |
| Location | `locations`, `remote`, `remotePolicy` (REMOTE / ONSITE\_OR\_REMOTE / ONSITE), `remoteLocations` |
| Pay | `compensation` (as shown), `salaryMin`, `salaryMax`, `salaryCurrency`, `hasEquity`, `equityMinPct`, `equityMaxPct` |
| Company | `companyName`, `companyId`, `companyUrl`, `companyLogo`, `companyTagline`, `companySize`, `companyStage` |
| Company signals | `activelyHiring`, `ycFunded`, `topInvestors`, `valuation` ($500M+ / $1B+), `recentlyFunded`, `growingFast`, `b2b`, `b2c`, `glassdoorRating`, `workLifeBalanceRating`, `leadershipRating`, `respondsWithin`, `topResponder`, `badges` |
| Job details (optional) | `visaSponsorship`, `relocationAllowed`, `recruiterRecentlyActive`, `salaryPeriod`, `industry`, `benefits`, `companyWebsite`, `geo` (lat/lng), `descriptionHtml` |
| All jobs per company (optional) | `totalRaisedUsd`, `companyWebsite`, `linkedInUrl`, `twitterUrl`, `markets`, `companyLocations`, `companyLiveJobCount` |

Every row has every column (empty when not applicable), so CSV and Excel exports stay consistent.

#### Sample row

```json
{
  "jobId": "4639821",
  "title": "Software Engineer",
  "companyName": "Checkr",
  "jobUrl": "https://wellfound.com/jobs/4639821-software-engineer",
  "postedAt": "2026-08-27T20:06:24.000Z",
  "jobType": "full-time",
  "primaryRole": "Software Engineer",
  "locations": ["Denver", "San Francisco"],
  "remote": false,
  "compensation": "$150k – $176k",
  "salaryMin": 150000,
  "salaryMax": 176000,
  "salaryCurrency": "USD",
  "companySize": "501-1000",
  "companyStage": "Scale Stage",
  "ycFunded": true,
  "topInvestors": true,
  "valuation": "$1B+",
  "glassdoorRating": 4.1,
  "workLifeBalanceRating": 4.3,
  "respondsWithin": "within three weeks",
  "visaSponsorship": false,
  "relocationAllowed": false,
  "salaryPeriod": "YEAR",
  "geo": [{ "city": "Denver", "region": "Colorado", "country": "United States", "lat": 39.7392, "lng": -104.99 }],
  "atsSource": "Greenhouse",
  "search": "software-engineer @ san-francisco"
}
```

### How to use it

**Quick start:** a role and a location.

```json
{ "roles": ["software-engineer"], "locations": ["san-francisco"], "maxItems": 50 }
```

**Several searches at once.** Every role is searched in every location:

```json
{ "roles": ["product-manager", "data-scientist"], "locations": ["new-york", "remote"], "maxItems": 500, "maxItemsPerSearch": 150 }
```

**Only well-paid remote jobs at YC companies that sponsor visas:**

```json
{ "roles": ["backend-engineer"], "locations": ["remote"], "minSalary": 150000, "ycOnly": true, "visaSponsorshipOnly": true }
```

**Every open job at specific companies:**

```json
{ "companies": ["checkr", "https://wellfound.com/company/mercor"], "maxItems": 500 }
```

**One row per company** (with its jobs nested inside), handy for lead lists:

```json
{ "locations": ["toronto"], "outputMode": "companies", "maxItems": 200 }
```

#### Role and location names

Use the names from Wellfound's URLs: `wellfound.com/role/l/`**`software-engineer`**`/`**`new-york`**. Plain words are converted automatically ("Software Engineer" → `software-engineer`, "NYC" → `new-york`, "Bengaluru" → `bangalore`). If Wellfound doesn't recognise a name, that search is skipped with a message rather than returning unrelated jobs.

Common roles: `software-engineer`, `frontend-engineer`, `backend-engineer`, `full-stack-engineer`, `machine-learning-engineer`, `data-scientist`, `data-engineer`, `devops-engineer`, `product-manager`, `product-designer`, `designer`, `marketing`, `sales`, `operations-manager`, `recruiter`, `finance`.

#### Filters

`postedWithinDays`, `remoteOnly`, `jobTypes`, `minSalary`, `equityOnly`, `companyStages`, `companySizes`, `ycOnly`, `visaSponsorshipOnly`, `titleKeywords`, `excludeTitleKeywords`. Filtered-out jobs are not saved and not charged.

### How complete are the results?

- **Every company in a search is covered.** Wellfound reshuffles results while you page through them, which makes naive scrapers skip some companies and repeat others. This actor removes duplicates and re-reads the search when companies are missing. In our tests it reached 100% of the companies Wellfound reports.
- **Up to 3 jobs per company from search pages.** That is what Wellfound shows on its search pages. The run's status message tells you how many jobs Wellfound lists in total, so you can see the gap. Turn on **All jobs per company** to open each company and collect every open job. That mode is thorough but slow (about a minute per company page), so use it with a sensible `maxItems` or for a list of specific companies.

### Use cases

- **Job seekers**: pull every senior backend role with a real salary range and visa sponsorship into a spreadsheet.
- **Recruiters and staffing agencies**: see which startups are hiring for which roles, how fast they respond, and what they pay.
- **Sales and lead generation**: build lists of funded, growing startups (stage, size, YC, $1B+ valuation, funding raised) that are actively hiring.
- **Market and compensation research**: salary and equity bands by role, city, company stage and size.
- **Job boards and newsletters**: fresh startup postings with dates, descriptions and apply links, on a schedule.

### FAQ

**Do I need a Wellfound account or cookies?** No. The actor only reads public pages.

**How fresh is the data?** Pages are loaded fresh on each run (`freshResults`, on by default), so postings from minutes ago show up. `postedAt` is the date the job went live.

**How fast is it?** A search page (20 companies, ~40 jobs) takes 2–4 seconds, and pages load in parallel. 500 jobs usually take under a minute. Job details add one quick page per job. "All jobs per company" is much slower.

**Why does the total Wellfound shows differ from what I got?** Search pages show at most 3 jobs per company. Use "All jobs per company" for the rest. Filters and `maxItems` also reduce the count.

**Is salary always yearly?** Wellfound shows yearly ranges for most jobs. With job details on, `salaryPeriod` states the period explicitly. Salaries are in the job's own currency (`salaryCurrency`).

**Which proxy should I use?** Keep the default residential proxy. Datacenter proxies are refused by Wellfound.

**What if my Apify plan has no residential proxies?** The actor checks your plan's proxy access at the start of the run. If it has Apify's unblocker proxy group, every page goes through that instead: slower, and job details (salary range, visa and relocation labels) are skipped, so the "Visa sponsorship only" filter can't run. If your plan has neither, the run ends within seconds with 0 items and no charge, and the status message tells you what to enable in Apify Console → Proxy. Full company job lists always need the unblocker group; without it those company pages are skipped and the jobs from search pages are kept.

**Can I schedule it?** Yes. Use Apify Schedules with `postedWithinDays: 1` to collect each day's new startup jobs.

**What happens if Wellfound blocks requests, or something goes wrong mid-run?** The run still finishes as *succeeded* with everything collected so far and a status message that says what happened (for example "Partial — stopped at a Wellfound-wide block: 240 jobs saved"). Every request is retried on a fresh IP with backoff; if the residential route is challenged wholesale the run moves to Apify's unblocker proxy; the run stops itself a minute before its timeout so results are always flushed. You are charged only for rows that are actually in the dataset — never for errors, filtered-out jobs, failed detail pages or company pages whose jobs did not make it into the results.

**My input uses different field names.** Common aliases are accepted: `maxResults` / `limit` for `maxItems`, `query` / `keywords` / `jobTitle` for `roles`, `location` / `city` / `country` for `locations`, `urls` for `startUrls`, `fetchJobDetails` for `includeJobDetails`, `daysAgo` for `postedWithinDays`, and so on. Comma-separated strings work where a list is expected, and "Toronto, ON" or "San Francisco, CA" resolve to the right city. Unusable input never fails the run — it ends with 0 items and a message explaining what to change.

**Is it legal to scrape Wellfound?** This actor collects only publicly available data: the job postings and company profiles Wellfound shows to any visitor without logging in. Job descriptions are written by the hiring companies and occasionally include a contact name or work email that the company chose to publish, so your results may contain some personal data. Use it for a legitimate purpose and in line with the privacy laws that apply to you (such as GDPR, PIPEDA or CCPA) and Wellfound's terms. If you are unsure about your use case, check with a lawyer. More background: [Is web scraping legal?](https://blog.apify.com/is-web-scraping-legal/)

**Does it access any private data?** No. It reads only public pages, with no login, cookies or Wellfound account. It never touches candidate profiles, applications, messages or anything behind a sign-in, and it deliberately leaves out the recruiter / hiring-contact names that Wellfound shows on some job pages. The only people-related text in your results is whatever a company wrote into its own public job description.

# Actor input Schema

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

Job roles as Wellfound names them, e.g. software-engineer, product-manager, data-scientist, designer, frontend-engineer, backend-engineer, full-stack-engineer, machine-learning-engineer, devops-engineer, marketing, sales. Plain words work too ("Software Engineer"). Each role is searched in every location below.

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

Cities or countries as they appear in Wellfound URLs, e.g. san-francisco, new-york, toronto, london, bangalore, united-states. Use "remote" for remote-only jobs. Leave empty to search a role worldwide; without roles, each location returns all its startup jobs.

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

Wellfound pages to scrape directly: role pages (wellfound.com/role/software-engineer), role + location (/role/l/software-engineer/new-york), remote roles (/role/r/data-scientist), locations (/location/toronto), single jobs (/jobs/4639821-software-engineer) or companies (/company/checkr — all their jobs).

## `companies` (type: `array`):

Company names or Wellfound slugs (checkr, mercor) or company URLs. Returns every open job of each company plus funding raised, website, LinkedIn/X links and markets. Company pages load slowly (about a minute each).

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

Maximum number of jobs (or companies in companies mode) for the whole run.

## `maxItemsPerSearch` (type: `integer`):

Cap for each role × location search, so one broad search cannot use up the whole run. Leave empty for no per-search limit.

## `outputMode` (type: `string`):

Jobs: one row per job with its company's details. Companies: one row per company with its jobs nested inside.

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

Open each job's page to add visa sponsorship, relocation, recruiter activity, benefits, industry, company website, salary period and map coordinates. One extra page per job.

## `includeAllCompanyJobs` (type: `boolean`):

Wellfound's search pages show up to 3 jobs per company. Turn this on to open each company found and collect ALL its open jobs, plus funding raised, website, LinkedIn/X and markets. Company pages take about a minute each, so runs are much slower.

## `maxPagesPerCompany` (type: `integer`):

With 'All jobs per company': cap on company job pages (20 jobs each). Leave empty for all.

## `postedWithinDays` (type: `integer`):

Only jobs posted in the last N days.

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

Only jobs that can be done remotely (fully remote or remote-or-onsite).

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

Only these job types. Empty = all.

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

Only jobs whose salary range reaches at least this yearly amount (in the job's own currency, e.g. 150000). Jobs without a listed salary are skipped when this is set.

## `equityOnly` (type: `boolean`):

Only jobs that list an equity range.

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

Only companies at these stages. Empty = all.

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

Only companies of these sizes (employees). Empty = all.

## `ycOnly` (type: `boolean`):

Only companies backed by Y Combinator.

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

Only jobs whose page says visa sponsorship is available. Turns on job details automatically.

## `titleKeywords` (type: `array`):

Keep a job only if its title contains one of these words (e.g. senior, backend, react).

## `excludeTitleKeywords` (type: `array`):

Skip jobs whose title contains any of these words (e.g. intern, manager).

## `maxPagesPerSearch` (type: `integer`):

Each search page lists 20 companies. Leave empty to read every page.

## `freshResults` (type: `boolean`):

On (recommended): every page is loaded fresh, so new postings show up immediately and paging is consistent. Off: slightly faster, but pages can be up to a day old.

## `maxPasses` (type: `integer`):

Wellfound reshuffles results while you page through them. If companies are still missing after the first pass, the search is read again (up to this many passes).

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

Parallel page loads.

## `useUnblockerFallback` (type: `boolean`):

If normal residential requests start getting challenged, retry through Apify's unblocker proxy (slower). Company pages always need it.

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

Residential proxy is required — Wellfound challenges datacenter IPs. A new IP is used for every request.

## `_noUnblocker` (type: `boolean`):

Internal (canaries): behave exactly like an account without the UNBLOCKER proxy group.

## `_noResidential` (type: `boolean`):

Internal (canaries): behave exactly like an account without the RESIDENTIAL proxy group.

## Actor input object example

```json
{
  "roles": [
    "software-engineer"
  ],
  "locations": [
    "san-francisco"
  ],
  "maxItems": 50,
  "outputMode": "jobs",
  "includeJobDetails": false,
  "includeAllCompanyJobs": false,
  "remoteOnly": false,
  "equityOnly": false,
  "ycOnly": false,
  "visaSponsorshipOnly": false,
  "freshResults": true,
  "maxPasses": 2,
  "maxConcurrency": 10,
  "useUnblockerFallback": true,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  },
  "_noUnblocker": false,
  "_noResidential": false
}
```

# Actor output Schema

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

All scraped jobs.

## `run` (type: `string`):

Status and statistics for this run.

# 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": [
        "san-francisco"
    ],
    "maxItems": 50,
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ]
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("yugenox/wellfound-startup-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": ["san-francisco"],
    "maxItems": 50,
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
    },
}

# Run the Actor and wait for it to finish
run = client.actor("yugenox/wellfound-startup-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": [
    "san-francisco"
  ],
  "maxItems": 50,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}' |
apify call yugenox/wellfound-startup-jobs-scraper --silent --output-dataset

```

## MCP server setup

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