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

Build startup-job shortlists from Wellfound by role, location and remote filter. Export job descriptions, disclosed salary and equity, company details and apply links for recruiting research or job feeds. No Wellfound login required.

- **URL**: https://apify.com/keystonelabs/wellfound-jobs-scraper.md
- **Developed by:** [Nick McNemar](https://apify.com/keystonelabs) (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

$2.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?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

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

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

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

# README

## Build a startup-job shortlist with salary and remote details

Collect Wellfound jobs by role, location and remote filter, then inspect company details, descriptions, disclosed salary and equity, and apply links. Remote roles may have geographic restrictions. Use the output for recruiting research or a job-feed workflow.

### Get a useful first result

1. Open the Input tab and select JSON. Paste the small example below.
2. Check Pricing and set your run spending limit, then start the run.
3. Inspect `title`, `salaryMin`, `salaryMax`, `location`, `acceptedRemoteLocations` and `url`.
4. Export the result as JSON or CSV. Check a small sample before increasing the input size.

```json
{
  "roles": [
    "software-engineer"
  ],
  "remoteOnly": true,
  "maxItems": 20
}
```

The sample incurs $0.040 in Actor event fees if it returns the intended number of rows. The rate checked September 7, 2026 is $2.00 per 1,000 output rows. Check the live Pricing tab before running; taxes or other account services may be separate.

### What can I use it for?

- **Job boards and aggregators.** Pull fresh startup openings by role or city and republish them with salary and remote data already parsed.
- **Recruiting and sourcing.** Find which startups are hiring for a given role right now, which are marked Actively Hiring, and which applicant tracking system they post through.
- **Lead generation.** A company that just posted five engineering roles at 11-50 employees is a strong signal for sales, recruiting and dev-tools vendors. Filter by company size, stage, business model or YC funding.
- **Compensation research.** Disclosed salary and equity ranges are parsed into structured fields. Coverage varies with the source listings.
- **Remote-work research.** The accepted remote locations list shows exactly where a remote role can be hired, which is rare structured data.
- **Job alerts.** Schedule a run with the posted-within-days filter to catch new listings for a role.

### What data does it return?

One item per unique job. The fields buyers filter on most are at the top level so the dataset works in a spreadsheet without post-processing.

| Field | Example |
|---|---|
| `id`, `title`, `url` | `4322508`, `Software Engineer`, `https://wellfound.com/jobs/4322508-software-engineer` |
| `companyName`, `companySlug`, `companyUrl`, `companyLogoUrl` | `FutureFit AI`, `futurefit-ai-2` |
| `companyPitch` | `AI-powered GPS for your Career` |
| `companySize` | `11-50` |
| `companyStage` | `Early Stage`, `Growth Stage`, `Scale Stage`, `Public Stage` |
| `companyBusinessModel` | `B2B`, `B2C` |
| `companyActivelyHiring`, `companyYcFunded` | `true` / `false` |
| `companyBadges` | `["Actively Hiring", "Top Investors", "Valuation $1B+"]` |
| `compensation` | `$150k – $185k • 0.1% – 0.5%` (raw string as shown on Wellfound) |
| `salaryMin`, `salaryMax`, `salaryCurrency` | `150000`, `185000`, `USD` |
| `equityMin`, `equityMax` | `0.1`, `0.5` (percent; `0` when the listing says No equity; `null` when unstated) |
| `jobType` | `full-time`, `contract`, `internship` |
| `remote`, `remoteKind`, `wfhFlexible` | `true`, `REMOTE` / `ONSITE_OR_REMOTE` / `ONSITE`, `false` |
| `location`, `locations` | `New York City, Boston`, `["New York City", "Boston"]` |
| `acceptedRemoteLocations` | `["United States", "Canada"]` |
| `primaryRole` | `Software Engineer` (Wellfound's normalized role) |
| `yearsExperienceMin`, `yearsExperienceMax` | `3`, `null` |
| `atsSource` | `Greenhouse`, `Ashby`, `Lever`, `Workable`, or `null` for jobs posted natively |
| `autoPosted` | `false` |
| `postedAt`, `postedAtTimestamp` | `2026-09-03T14:22:22.000Z`, `1788445342` |
| `description` | Full job description in markdown |
| `searchRole`, `searchLocation`, `searchRemote`, `sourceUrl` | Which feed and page produced the item |
| `scrapedAt` | `2026-09-04T21:03:11.104Z` |

#### Illustrative output

The example below explains the output shape; values are illustrative and are not a live result or a promise that every field is populated.

```json
{
  "id": "4322508",
  "title": "Software Engineer",
  "url": "https://wellfound.com/jobs/4322508-software-engineer",
  "companyName": "FutureFit AI",
  "companySlug": "futurefit-ai-2",
  "companyUrl": "https://wellfound.com/company/futurefit-ai-2",
  "companyPitch": "AI-powered GPS for your Career",
  "companySize": "11-50",
  "companyStage": "Early Stage",
  "companyBusinessModel": "B2B",
  "companyActivelyHiring": true,
  "companyYcFunded": false,
  "companyBadges": ["Actively Hiring", "B2B", "Early Stage", "Growing fast"],
  "compensation": "$150k – $185k",
  "salaryMin": 150000,
  "salaryMax": 185000,
  "salaryCurrency": "USD",
  "equityMin": null,
  "equityMax": null,
  "jobType": "full-time",
  "remote": true,
  "remoteKind": "REMOTE",
  "wfhFlexible": false,
  "location": "New York City",
  "locations": ["New York City"],
  "acceptedRemoteLocations": ["United States"],
  "primaryRole": "Software Engineer",
  "yearsExperienceMin": null,
  "yearsExperienceMax": null,
  "atsSource": "Ashby",
  "autoPosted": false,
  "postedAt": "2026-09-01T08:00:00.000Z",
  "postedAtTimestamp": 1788307200,
  "description": "**Come join our Engineering team!** ...",
  "searchRole": "software-engineer",
  "searchLocation": null,
  "searchRemote": true,
  "sourceUrl": "https://wellfound.com/role/r/software-engineer?page=1",
  "scrapedAt": "2026-09-04T21:03:11.104Z"
}
```

### How to use it

1. Enter one or more **Job roles**. Use the slug from Wellfound's URL (`software-engineer`, `backend-engineer`, `product-manager`, `data-scientist`, `devops-engineer`, `sales-engineer`, `account-executive`). Plain names like `Software Engineer` are converted for you. Wellfound publishes more than 500 role feeds.
2. Optionally add **Locations** (`new-york`, `san-francisco`, `austin`, `boston`, `denver`, `seattle`, `chicago`, `district-of-columbia`, `united-states`, `india`) and tick **Remote jobs only**.
3. Set **Maximum jobs** and click **Start**. The default input returns 20 remote software engineering jobs and finishes in a few seconds.
4. Download the dataset as JSON, CSV or Excel from the **Output** tab, or read it through the API.

Use **Keywords** to keep only listings mentioning a technology or domain, and **Posted within the last N days** to restrict to fresh postings. Advanced users can paste Wellfound search URLs directly into **Wellfound listing URLs**.

#### Input example

```json
{
  "roles": ["software-engineer", "backend-engineer"],
  "locations": ["new-york", "san-francisco"],
  "remoteOnly": false,
  "keywords": ["React", "TypeScript"],
  "postedWithinDays": 14,
  "maxItems": 500
}
```

That input searches four role x location feeds, keeps only jobs mentioning React or TypeScript that were posted in the last two weeks, and stops at 500 unique jobs.

### How it works

Wellfound's public role and location pages ship every listing for the current page inside the HTML as a normalized Apollo cache, including the full description, compensation string and company summary. The actor requests those pages with a normal browser user agent, parses the embedded JSON, joins each job to its company and badges, parses the compensation string into numeric salary and equity fields, and pushes each job to the dataset as soon as it is ready.

Jobs are deduplicated by ID across all feeds in a run, so the same posting appearing under several roles or locations is stored once. Pagination follows the page count Wellfound reports and stops at Wellfound's own ceiling of 47 pages per feed, on the first empty page, or when the maximum has been reached.

Compensation strings use an en dash between values and a bullet between salary and equity, and appear in several currencies (`$`, `£`, `€`, `₹`, with occasional suffixes such as `CAD`). The parser handles ranges, single values, `Up to` forms, `No equity`, thousand and lakh multipliers and currency codes.

### Pricing

You pay per job saved to the dataset. Duplicates are removed before saving, so you are never charged twice for the same listing. There are no subscriptions or minimums, and you can cap the maximum spend of a run before starting it.

### Scope and responsible use

The actor reads only Wellfound's public, logged-out search pages, exactly as a visitor's browser does. It requires no account, cookies or credentials, does not touch pages that sit behind Wellfound's security check, and does not attempt to bypass any bot protection or access control. It respects Wellfound's robots.txt, which permits the role and location feeds it uses. The data consists of company job postings, not personal data. Keep run sizes reasonable and use the results in accordance with the laws that apply to you and Wellfound's terms.

### Limitations

- Each feed stops at 47 pages, roughly 1,500 to 1,900 jobs. To go wider, combine several roles and locations rather than paging deeper.
- Company detail pages (funding, team, full company profile) are not accessible without a login and are out of scope. Company fields come from the summary embedded in the listing feed: name, slug, logo, one-line pitch, size band, stage and badges.
- Salary is present on about 84% of listings and equity on under 10%; years of experience on about a third. Missing values are `null`.
- Wellfound caches its search pages for up to about a day, so a listing can be a few hours behind the live site. Use `postedAt` rather than scrape time to judge freshness.
- Keyword filtering is applied to the scraped text; it does not use Wellfound's own search, which is not available to logged-out visitors.
- Location slugs must match Wellfound's; an unknown slug is reported in the log and skipped.

### Something missing?

Open an issue on this actor's **Issues** tab with the input you used and what you expected. Layout changes on Wellfound are usually handled within days.

### Before a larger run

Only returned job rows incur the per-row event fee; an empty result is not evidence that no matching jobs exist on the source. These are paid examples, not a free-results offer. No source-site API key is needed for the example in Console; programmatic Apify API access still requires Apify authentication.

Five internal launch smoke rounds passed on September 6, 2026. This describes small-input test coverage, not customer reviews, a service-level guarantee or a large-batch benchmark. Website behavior and data availability can change.

# Actor input Schema

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

Roles to search, one per line, as they appear in Wellfound URLs: software-engineer, product-manager, data-scientist, devops-engineer, sales-engineer, backend-engineer and 500+ more. Plain names such as 'Software Engineer' are converted automatically. Each role becomes one search feed.

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

Optional location filter, one per line, as Wellfound location slugs: new-york, san-francisco, austin, boston, denver, seattle, chicago, los-angeles, district-of-columbia, united-states, india, london. Combined with Job roles, every role x location pair is searched. Leave empty to search all locations.

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

Return only jobs that are open to remote work.

## `keywords` (type: `array`):

Optional. Keep only jobs whose title, company name or description contains at least one of these terms (case-insensitive), for example React, Kubernetes, fintech.

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

Optional. Skip jobs posted more than this many days ago. 0 disables the filter.

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

Optional. Paste Wellfound search pages directly, for example https://wellfound.com/role/r/backend-engineer, https://wellfound.com/role/l/software-engineer/new-york or https://wellfound.com/location/austin. Company pages are not supported.

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

Stop after this many unique jobs have been saved across all feeds. Each Wellfound feed exposes at most 47 pages (roughly 1,500 to 1,900 jobs), so combine several roles or locations to go wider.

## `maxPagesPerFeed` (type: `integer`):

How deep to page into each role or location feed. Wellfound serves at most 47 pages per feed; each page holds 30 to 60 jobs.

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

How many feeds to scrape in parallel. Keep it low; one request already yields about 40 jobs.

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

Optional. Route requests through Apify Proxy if Wellfound starts answering with a security check from your IP range.

## Actor input object example

```json
{
  "roles": [
    "software-engineer"
  ],
  "locations": [],
  "remoteOnly": true,
  "keywords": [],
  "postedWithinDays": 0,
  "startUrls": [],
  "maxItems": 20,
  "maxPagesPerFeed": 47,
  "maxConcurrency": 2,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `jobs` (type: `string`):

Dataset of scraped Wellfound job listings. Each item is one job with parsed salary and equity, locations, remote policy, full markdown description, posted date and company size, stage and badges.

# 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": [],
    "remoteOnly": true,
    "keywords": [],
    "startUrls": [],
    "maxItems": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("keystonelabs/wellfound-jobs-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "roles": ["software-engineer"],
    "locations": [],
    "remoteOnly": True,
    "keywords": [],
    "startUrls": [],
    "maxItems": 20,
}

# Run the Actor and wait for it to finish
run = client.actor("keystonelabs/wellfound-jobs-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "roles": [
    "software-engineer"
  ],
  "locations": [],
  "remoteOnly": true,
  "keywords": [],
  "startUrls": [],
  "maxItems": 20
}' |
apify call keystonelabs/wellfound-jobs-scraper --silent --output-dataset

```

## MCP server setup

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