Wellfound Startup Jobs Scraper
Pricing
from $2.50 / 1,000 dataset items
Wellfound Startup Jobs Scraper
Find and monitor startup roles for recruiters, analysts, and job seekers. Returns structured compensation, remote-work, company, location, and listing details. Includes compact output for agent workflows.
Pricing
from $2.50 / 1,000 dataset items
Rating
0.0
(0)
Developer
NaNomicon
Maintained by CommunityActor stats
1
Bookmarked
2
Total users
1
Monthly active users
12 hours ago
Last modified
Categories
Share
Scrape Wellfound (formerly AngelList) startup job listings — structured salaries, equity, remote policy, and company data. Built for recruiters, analysts, job-seekers, and AI agents.
Why this one over the alternatives:
- Fails loudly. Zero results or a site change = explicit error naming what broke — never a silent empty run burning your quota (the #1 complaint about other Wellfound scrapers).
- Fresh and maintained. Daily builds; when the site changes we ship fixes within a day.
- Cheap. Low platform usage we pass on to you.
- Incremental by default. Repeat runs emit only NEW jobs — build job alerts without deduplicating anything yourself.
- Webhook notifications. Optional secret
webhookUrlreceives one JSON notification after each run writes newly emitted jobs. - Stale-tolerant cache mode. $0.0005/result snapshots for agents that want bulk data fast and accept some staleness.
What you get
| Field | Example |
|---|---|
title | Senior Backend Engineer |
company | Virta Health |
comp | $114k – $148k |
salaryMin / salaryMax / salaryCurrency | 114000 / 148000 / USD |
equityMinPct / equityMaxPct | 0.1 / 0.5 |
jobType | full-time |
remote / remoteKind | true / "worldwide" |
locations | ["United States"] |
yearsExperienceMin / yearsExperienceMax | 2 / 5 |
postedAt | 1791847814 (unix) |
description | byte-identical text excerpt by default |
companyUrl | direct startup profile URL |
companySize, companyHighConcept, companyLogoUrl | with enrich: true; no extra fetches or charges |
companyBadges | complete set of distinct, non-empty badge labels in first-seen order; whitespace-only labels ignored; labels kept verbatim; no badge-name allowlist |
companyStage / companyFundingStage | machine-readable funding-stage token / display label from the same stage badge; token kept verbatim with no token allowlist |
companyYcFunded | true when the company carries a YC badge |
descriptionMarkdown | optional; when descriptionFormat: "markdown" |
descriptionHtml | optional; when descriptionFormat: "html" |
url | direct job listing URL |
With enrich: true, matching job rows include available company fields from
data collected during the crawl. These fields add no fetches or charges.
A missing company badge or funding-stage field means the source did not report
a usable value for it — not that the company has no stage and is not YC-backed;
the actor omits the key and never emits null. company-rollups
always includes per-company open-role counts, salary medians, recent hiring,
top titles, and remote share; rollups are free. The five single-valued company
string fields (companySize, companyHighConcept, companyLogoUrl,
companyStage, companyFundingStage) use the most frequent value across the
company's jobs, with ties broken alphabetically. companyBadges in a rollup
row is the ordered distinct union across the company's jobs; companyYcFunded
is true if any of the company's jobs carries it.
companyStage is the machine-readable funding-stage token, taken verbatim
from the stage badge; companyFundingStage is the display label of that same
badge. companyYcFunded is true when the company carries a YC badge.
description remains the byte-identical default text excerpt;
descriptionMarkdown or descriptionHtml is returned only when the matching
format is requested.
Quick start
- Run with defaults — crawls software-engineer + backend-developer roles.
- Second run with the same input emits only newly posted jobs.
- Set
compact: truefor core fields only; setenrich: trueto include available company fields at no extra charge.
{"roleSlugs": ["software-engineer", "backend-developer"],"keywords": [],"locations": [],"maxJobs": 500,"maxFetches": 30,"postedWithinDays": 7,"minComp": 100000,"compact": false,"enrich": false,"descriptionFormat": "text"}
roleSlugs, keywords, and locations suggestions are non-exhaustive; custom
slugs are allowed. To find a slug, open the matching Wellfound page and copy
the URL path segment: after /role/r/ for roleSlugs, after /role/ for
job-title keywords, or after /location/ for locations. Enter the slug,
not the full URL or display name. For example, /location/new-york-city-ny
uses slug new-york-city-ny. Wellfound pages and available listings can change.
Webhooks and description formats
- Webhook notifications. Optional secret
webhookUrlreceives oneapplication/jsonPOST per run after dataset output is written, only when fresh jobs were emitted. Payload includesrunId,actorId,runUrl,counts(new,totalEmitted), up to 50 newest compactjobs,datasetUrl, andcrawledAt. Webhook failures warn but do not fail the run or lose data; requests time out after 10 seconds and retry once. - Description format.
descriptionFormatacceptstext(default),markdown, orhtml. Defaultdescriptionexcerpt stays byte-identical; requested formats add optionaldescriptionMarkdownordescriptionHtml.
Pricing
- $0.01 per run (
apify-actor-start). - $0.0025 per fresh job (
apify-default-dataset-item). - $0.0005 per cached job (
cached-result). - A 1,000-job fresh run ≈ $2.51. Company fields with
enrich: trueadd no fetches or charges.
Filters
roleSlugs— remote role pages; suggested values are non-exhaustive; custom Wellfound slugs are allowed.keywords— additional job-title slugs, not arbitrary free-text keywords; fetched as general Wellfound role pages.locations— location slugs; suggestions are non-exhaustive; custom values are slugified before fetching.postedWithinDays— only jobs posted in the last N days.minComp/minYears— lower bounds on salary / required experience.maxJobsdefaults to500;maxFetchesdefaults to30and caps role and seed-page fetches only.enrich— include available company fields; output toggle, no extra fetch or charge; defaultfalse.descriptionFormat—text(default),markdown, orhtml; default text description is unchanged.webhookUrl— optional secret endpoint; one post after emitted jobs are written, fail-soft with one retry.cached/maxCacheAgeHours— snapshot serving and its freshness limit.
Recipes
- Job alert: schedule identical input with
postedWithinDaysandmaxJobs. Incremental state emits only new jobs; read the default dataset after each successful run and use a webhook to trigger downstream processing.
Reliability contract
- Crawl fails loudly on: zero usable results, unparseable site state, missing company anchors, >5% fetch errors. Every failure names the cause.
- Incremental state is keyed to your exact input — change the input, get a clean partition. Clear the actor's key-value store to reset.
- Memory-capped 256–1024 MB: predictable platform cost.
For AI agents
Machine-readable docs: ./AGENTS.md — exact input/output schemas,
pricing events, error semantics, and a copy-paste run command. Output fields
are stable; compact: true returns the core subset agents need. If you are
driving this actor from an LLM tool-call, read AGENTS.md, not this README.
Store sync
scripts/sync_store_state.py compares live Store metadata with .actor/store-state.desired.json; read-only by default, --apply writes.
--publish authorizes public flips; --unpublish authorizes private flips; neither authorizes the other.
Both checks are change-based: an apply leaving isPublic unchanged needs no flag. Refused apply sends no request; refusal happens before the write.
Visibility flips are human decisions; the tool refuses to guess.
Store categories are pinned to JOBS, LEAD_GENERATION, AGENTS in
.actor/store-state.desired.json; --apply writes them (no flag needed —
categories are not a visibility flip).
The Store's example run input is kept in .actor/example-run-input.json; set
it on the actor's exampleRunInput field so a Console test run uses a real
input instead of the template placeholder. scripts/set_example_run_input.py
applies it (--check to compare, --dry-run to preview; a bare run applies);
the Apify CLI cannot set this field, so the script updates the actor's
exampleRunInput field through the documented actor update endpoint (only
that field is sent).
FAQ
Is this affiliated with Wellfound? No. Independent public-data extraction. Why does a run return 0 results but succeed? It doesn't — empty crawls fail with a reason. A successful run with no NEW jobs means everything was already emitted (incremental mode working). Blocked or empty? Open an issue with the run ID — failures are explicit by design, so support starts from the real error.