Wellfound Jobs Scraper By Remote, Seniority & Salary Filter avatar

Wellfound Jobs Scraper By Remote, Seniority & Salary Filter

Pricing

from $3.99 / 1,000 results

Go to Apify Store
Wellfound Jobs Scraper By Remote, Seniority & Salary Filter

Wellfound Jobs Scraper By Remote, Seniority & Salary Filter

Wellfound Jobs Scraper extracts public job listings from Wellfound, including job titles, company names, locations, salary ranges, skills, job descriptions, employment types, and application URLs. Ideal for recruitment, job market research, salary analysis, and hiring insights.

Pricing

from $3.99 / 1,000 results

Rating

0.0

(0)

Developer

Scrapio

Scrapio

Maintained by Community

Actor stats

0

Bookmarked

1

Total users

0

Monthly active users

4 days ago

Last modified

Share

Wellfound Jobs Scraper By Remote, Seniority & Salary Filter

Scrape startup job listings from Wellfound (formerly AngelList Talent) and get them pre-sorted by the shape of the role, not just the keyword: onsite / remote / hybrid workplace type, a seniority band computed from a real years-of-experience number, an advertised salary floor, and company exclusions. Unlike scraping frameworks that return raw HTML, this Actor returns typed JSON — one flat row per job, ready for a spreadsheet, a database, or an LLM context window without any parsing. Two of the headline fields (workplace type, years of experience) are genuinely published on a minority of Wellfound listings, and this guide covers exactly how that partial coverage is handled, what every output field means, and how teams deploy the Actor in real pipelines.

What Does the Wellfound Jobs Scraper Do?

This Actor crawls Wellfound's public job search and listing pages — by city, by role keyword, by company, or from pasted job URLs — and returns one structured record per job posting. No Wellfound account, login, or cookies are required; every field comes from pages Wellfound serves to an anonymous visitor. On top of the standard listing fields (title, company, location, salary text, job type, posting age, description) it adds a role-shape layer: a workplace-type classification read from Wellfound's own remoteConfig field, a minimum-years-of-experience number with its source clearly tagged, a derived seniority band, and structured job-page geo (city / region / country / latitude / longitude).

  • Crawls Wellfound search pages by location (/location/<city>), by role (/role/r/<keyword>), by role plus location (/role/l/<keyword>/<city>), or from a raw keyword search on /jobs
  • Accepts individual Wellfound job detail URLs directly, bypassing the search step entirely
  • Classifies workplace type (ONSITE / REMOTE / HYBRID) from Wellfound's remoteConfig.kind, never from guessing at the word "Remote" in a location string
  • Extracts a published or regex-derived minimum years-of-experience figure and buckets it into an Entry / Mid / Senior / Lead-Principal band
  • Resolves exact job-page geo coordinates from the job's own schema.org JobPosting block
  • Filters on workplace type, remote-only, experience band, minimum salary, and excluded companies — each with explicit, auditable handling of roles that simply don't state the filtered field
  • Runs behind Apify residential sticky sessions by default, escalating proxy tiers automatically when Wellfound's anti-bot layer intervenes

Features & Capabilities

The Actor's feature set splits into what it extracts, how that stacks up against other Wellfound scrapers on the Apify Store, and where a different tool is the more honest recommendation.

Core capabilities, with the exact JSON keys each one writes to the dataset:

  • Workplace type from a real Wellfound field, not a guessworkplaceType (ONSITE/REMOTE/HYBRID), backed by workplaceTypeRaw (Wellfound's untouched token) and workplaceTypeKnown (whether the employer stated it at all)
  • Seniority derived from a number, never a job titleyearsExperienceMin, seniorityBand (ENTRY/MID/SENIOR/LEAD_PLUS), and experienceSource (wellfound_field when Wellfound published the number, description_regex when it was recovered from the description text)
  • A remote flag with no unknown caseisRemote, sourced from Wellfound's boolean remote field, which is present on effectively every listing
  • Where a remote hire may actually livewfhFlexible and acceptedRemoteLocations[]
  • Structured job geojobLocations[] with city, region, country, lat, lon per location, parsed from the job page's ld+json, plus a geoStatus explaining why it is null when it is
  • Salary floor filteringminAnnualSalary reads the same normalized salary string this Actor emits, so the filter and the visible field never disagree
  • Auditable filtering — every row that a partial-coverage filter would otherwise silently swallow is either kept and flagged in unknownFields[], or dropped as its own uncharged accounting row with a skipReason

How It Compares to Other Wellfound Scrapers

FeatureThis Actorkhadinakbar/wellfound-jobs-scraperabotapi/wellfound-jobs-scraper
Output formatTyped JSON datasetTyped JSON datasetTyped JSON dataset
Workplace type from remoteConfig (onsite/remote/hybrid)Yes, with a workplaceTypeKnown flagNot documented on their listing (observed 2026-07-26)Not documented on their listing (observed 2026-07-26)
Seniority band from a numeric years-of-experience fieldYes, with experienceSource auditing published vs. regex-derivedNot documented (observed 2026-07-26)Not documented (observed 2026-07-26)
Structured job geo (lat/lon per location)Yes, from schema.org JobPosting ld+jsonNot documented (observed 2026-07-26)Not documented (observed 2026-07-26)
Numeric salary fields (salaryMin/salaryMax/currency)No — a normalized salary string onlyYes, salaryMin, salaryMax, salaryCurrency (observed 2026-07-26)Yes, compensationMin, compensationMax, compensationCurrency (observed 2026-07-26)
Uncharged accounting rows for filtered-out unknownsYes, distinct skipReason per causeNot documented (observed 2026-07-26)Not documented (observed 2026-07-26)
Company exclusion filterYes, excludeCompaniesNot documented (observed 2026-07-26)Not documented (observed 2026-07-26)

If your use case is feeding structured data to an LLM or an automation pipeline, the output-format row is the decision-maker — parsing HTML or reconciling inconsistent field names inside an agent loop is a reliability failure mode, not a feature. Every row from this Actor carries the same key set whether the run returns one job or one thousand.

When Another Tool Might Suit You Better

If the primary need is a numeric salary and equity dataset with min/max/currency already split out, khadinakbar's Wellfound scraper documents salaryMin, salaryMax, salaryCurrency, equityMinPercent, and equityMaxPercent fields directly (observed on their listing, 2026-07-26) — this Actor keeps salary as a normalized string plus an internal filter, and does not expose split min/max/currency fields on the row. That competitor also documents a SerpApi-based fallback for recovering indexed job URLs when Wellfound blocks every browser request in a run, which this Actor does not implement. If workplace type, experience-band auditing, and structured job geo are not what you need, and a turnkey numeric compensation dataset is, that competitor is the better starting point.

Wellfound Jobs Scraper Within the Scrapio Data Stack

This Actor covers Wellfound job listings filtered by workplace type, seniority, and salary. For LinkedIn job postings with exact posting dates and repost detection, use LinkedIn Jobs Scraper: Exact Posting Dates & Reposts elsewhere in the Scrapio catalog. See the Related Scrapers section below for sibling Wellfound Actors that cover company firmographics, ATS/recruiting-stack signals, and numeric salary breakdowns instead of role shape.

Why Scrape Wellfound Job Data? (Audiences & Use Cases)

Wellfound is a startup-hiring signal source: postings often carry salary text, remote/hybrid status, seniority requirements, and a direct apply link, none of which require a login to read. The audiences below are the ones that genuinely use this kind of data — the same list applies whether you're building a workflow today or evaluating the Actor for a longer-term dependency.

Recruiters and Talent Sourcing Teams

🏢 A sourcing team filters workplaceTypes: ["REMOTE"], experience: "senior", and minAnnualSalary: 150000 against a target city, then routes the resulting job_title, company_name, and URL fields into an outreach queue for warm candidate conversations. unknownFields tells the recruiter when a role's workplace type wasn't confirmed by the employer, so it can be manually verified before it's used to disqualify a candidate search.

AI Training Data and RAG Indexing

📊 The description field is the high-information text for RAG indexing — full job-posting prose describing the role, stack, and requirements, generally present on the vast majority of cards and backfilled for the rest when fetchDescriptions is on. For training data, workplaceType, seniorityBand, job_type, and salary are the most consistently structured fields across records, since each is normalized to a small fixed vocabulary rather than free text. All fields return as typed primitives — strings, booleans, integers, or arrays — so no normalization step is required before indexing.

Competitive and Market Intelligence

📱 Analysts track company_name combined with workplaceType and salary over repeated runs to watch which startups are hiring for which roles, at what advertised pay, and whether they've shifted from onsite to remote hiring. A scheduled run over a target city or role keyword turns this into a rolling view of a startup segment's hiring posture.

Research and Academic Use

🔬 Labor-market and startup-hiring researchers use the workplace-type and years-of-experience fields, each tagged with its real coverage rate and source (workplaceTypeKnown, experienceSource), to study remote-work adoption and seniority demand without treating a partial-coverage field as a universal one. Scope is limited to what Wellfound publishes publicly.

Product and SaaS Development

🎥 Teams building a filtered startup job board, a remote-jobs directory, or a compensation-benchmarking product ingest the dataset directly — workplaceType, seniorityBand, salary, and jobLocations are already normalized, so the product layer doesn't need to write its own Wellfound parser.

🍚 Input Parameters

Every parameter below is read directly from .actor/actor.json's input schema, in schema order. None are required — the Actor falls back to the Wellfound /jobs landing page if no search target is supplied at all.

ParameterRequiredTypeDefaultDescription
startUrlsNoarray[]Wellfound search/listing pages (/location/new-york, /role/r/software-engineer, /role/l/data-scientist/remote) or individual job pages (/jobs/123456-role-slug). Takes priority over the search-builder fields below.
includeKeywordNostring""Role title, stack, or skill used to build the search URL when no Start URLs are given, e.g. software engineer, product designer.
locationNameNostring"New York"City or region the search URL is built around. Shapes which Wellfound page is crawled; per-job structured geo comes from resolveJobGeo instead.
companyNameNostring""Keep only cards whose company name loosely matches this value. Empty = every company.
pagesToFetchNointeger1 (min 1, max 100)Result pages to open per starting URL. A Wellfound listing page carries roughly 50 job cards, so 1 page is about 50 candidates before filtering.
workplaceTypesNoarray (enum: ONSITE, REMOTE, HYBRID)[]Keep only roles whose published workplace type is one of these, read from Wellfound's remoteConfig field (~27–29% coverage). Empty = accept any workplace type.
remoteOnlyNobooleanfalseKeep only roles flagged remote by Wellfound's 100%-coverage remote boolean.
experienceNostring (enum: "", entry, mid, senior, lead)""Keep only roles whose minimum years of experience falls in the matching band: Entry 0–1, Mid 2–4, Senior 5–8, Lead/Principal 9+. Computed from a published number or a marked regex fallback, never from a job title.
minAnnualSalaryNointeger0 (min 0, max 10000000)Drop roles whose advertised lower bound is below this figure, in the posting's own currency units. 0 disables the filter.
excludeCompaniesNoarray[]Company names to drop (case- and punctuation-insensitive substring match), e.g. ["Brex", "Deel"].
keepUnspecifiedNobooleantrueDecides what the workplace-type, experience, and salary filters do with a role that doesn't publish that field. On: kept, flagged in unknownFields. Off: dropped, and recorded as an uncharged accounting row with skipReason unknown_workplace_type / unknown_experience / unknown_salary.
resolveJobGeoNobooleantrueOpen each kept job page to read its schema.org data and emit jobLocations (city/region/country/lat/lon). Costs one extra request per job. Off = jobLocations is null and geoStatus reads not_requested.
maxGeoLookupsNointeger10 (min 0, max 200)Hard cap on job-page fetches used for location resolution. Jobs beyond the cap still get every listing-derived field, with geoStatus reading skipped_cap. 0 disables location resolution entirely.
jobTypeNostring (enum: "", FULLTIME, PARTTIME, CONTRACTOR, INTERN)""Filter by contract shape.
datePostedNostring (enum: all, today, 3days, week, month)"all"How recently the role was posted, matched against Wellfound's relative posting age.
fetchDescriptionsNobooleantrueFill in a description for the rare card whose listing payload ships without one. Costs nothing on cards that already have one.
countryNameNostring (enum: 249 ISO country/territory names)"United States"Proxy exit country. Geo-targets the connection only — it does not filter which jobs are returned; use locationName for that.
requestDelayNonumber1 (min 0, max 60)Base pause, plus jitter, before each result page loads. Raise it if Wellfound starts serving anti-bot stubs.
headlessNobooleantrueRun the browser headless. Turning it off is slower and only useful for debugging inside the container's virtual display.
proxyConfigurationNoobject{"useApifyProxy": false}Override the Actor's default residential sticky sessions with your own proxy configuration. Not a credential field — no API key or secret is required here.

Example input

{
"includeKeyword": "software engineer",
"locationName": "New York",
"pagesToFetch": 2,
"workplaceTypes": ["REMOTE", "HYBRID"],
"experience": "senior",
"minAnnualSalary": 150000,
"excludeCompanies": ["Brex", "Deel"],
"keepUnspecified": true,
"resolveJobGeo": true,
"maxGeoLookups": 20
}

Supported URL types and input formats

startUrls accepts three shapes, and takes priority over includeKeyword / locationName / companyName when present:

  • A city/region pagehttps://wellfound.com/location/new-york (paginated, roughly 50 cards per page)
  • A role page, with or without a locationhttps://wellfound.com/role/r/software-engineer or https://wellfound.com/role/l/data-scientist/remote
  • A single job detail pagehttps://wellfound.com/jobs/123456-role-slug, which the Actor detects and scrapes directly without opening a search page at all

When startUrls is empty, the Actor builds a search URL from the remaining fields: companyName set (with or without a keyword) builds /jobs?keywords=<company>[+keyword]; includeKeyword plus locationName builds /role/l/<keyword>/<location>; includeKeyword alone builds /role/r/<keyword>; locationName alone builds /location/<slug>. This last mapping is deliberate: Wellfound's generic /jobs?location=<slug> query parameter is ignored by the site and instead serves a non-paginated landing page hard-capped at roughly 49 featured cards, so a location-only search is routed to the genuine, paginated /location/<slug> page instead. If none of the four fields are set, the Actor falls back to the generic /jobs landing page and logs a warning that no real search target was supplied.

📦 Output Format

Every run writes to the Actor's default dataset. Rows come in three shapes, distinguished by rowType: job (the billable result), skipped (an uncharged accounting row), and run_summary (one uncharged row per run). The dataset's default view surfaces 25 of these columns; every key the Actor actually writes is documented below, including the two — workplaceTypeRaw and posted_via — that the default view omits.

Job Row Fields (the Main Output)

A job row carries every field below. This is a worked example with illustrative values, not a live scrape:

{
"job_title": "Senior Backend Engineer",
"company_name": "Vercel",
"location": "San Francisco, Remote",
"posted_via": "Wellfound",
"salary": "160K–210K a year",
"job_type": "Full-time",
"date": "3 days ago",
"URL": "https://wellfound.com/jobs/3324973-senior-backend-engineer?utm_campaign=google_jobs_apply&utm_source=google_jobs_apply&utm_medium=organic",
"description": "We are looking for a senior backend engineer to own our core API platform...",
"rowType": "job",
"jobId": "3324973",
"isRemote": true,
"workplaceType": "HYBRID",
"workplaceTypeRaw": "HYBRID",
"workplaceTypeKnown": true,
"wfhFlexible": true,
"acceptedRemoteLocations": ["United States", "Canada"],
"yearsExperienceMin": 5,
"seniorityBand": "SENIOR",
"experienceSource": "wellfound_field",
"yearsExperienceKnown": true,
"jobLocations": [
{ "city": "San Francisco", "region": "California", "country": "US", "lat": 37.7749, "lon": -122.4194 }
],
"geoStatus": "ok",
"unknownFields": [],
"runId": "8f2c1e9a-run",
"scrapedAt": "2026-07-26T14:03:11Z"
}
FieldTypeDescription
job_titlestringRole title.
company_namestringHiring company.
locationstringListing location as Wellfound displays it, or "Remote" when no location is listed but the role is flagged remote.
posted_viastringConstant "Wellfound", kept for field-name compatibility with the standard Wellfound scraper. Omitted from the default dataset view.
salarystringNormalized advertised compensation text — see the salary parsing rules below.
job_typestringFull-time / Part-time / Contract / Internship, normalized from Wellfound's raw label.
datestringRelative posting age as Wellfound shows it (e.g. "3 days ago").
URLstringCanonical job page link with UTM tracking parameters appended.
descriptionstringFull job description text, from the listing payload or the detail-page fetch.
rowTypestring"job" on billable rows.
jobIdstring | nullWellfound's numeric job identifier.
isRemotebooleanWellfound's remote flag. Present on effectively every listing — the only role-shape field with no unknown case.
workplaceTypestring | nullONSITE / REMOTE / HYBRID, normalized from Wellfound's remoteConfig.kind. null when not published (~71–73% of listings).
workplaceTypeRawstring | nullWellfound's untouched remoteConfig.kind token, before normalization. Omitted from the default dataset view.
workplaceTypeKnownbooleanWhether the employer published a workplace type at all.
wfhFlexibleboolean | nullWork-from-home flexibility flag, when Wellfound's remoteConfig states it.
acceptedRemoteLocationsarray | nullLocations a remote hire is allowed to live in, when Wellfound publishes them.
yearsExperienceMininteger | nullMinimum years of experience required, from a published field or a regex fallback.
seniorityBandstring | nullENTRY (0–1 yrs) / MID (2–4) / SENIOR (5–8) / LEAD_PLUS (9+), derived only from yearsExperienceMin. Never inferred from the job title.
experienceSourcestring | nullwellfound_field when Wellfound published yearsExperienceMin directly, description_regex when it was recovered from free-text prose, null when neither found a number.
yearsExperienceKnownbooleanWhether any experience number was obtained, from either source.
jobLocationsarray | null{city, region, country, lat, lon} per resolved location, parsed from the job page's schema.org JobPosting block. null when geo resolution didn't run or found nothing. A broadly-remote role can carry many location nodes.
geoStatusstringok / not_requested / skipped_cap / no_ldjson / no_location_in_ldjson / blocked — explains exactly why jobLocations is populated or not for this row.
unknownFieldsarrayNames of filtered fields this employer did not state, e.g. ["workplaceType"]. Empty array when nothing was missing.
runIdstringThe Apify run ID that produced this row.
scrapedAtstringISO-8601 UTC capture timestamp.

Skipped and Run-Summary Rows (Uncharged)

Two further row shapes appear in the same dataset, both pushed without a charged_event_name and therefore never billed.

A skipped row records why a card produced no billable result:

{
"rowType": "skipped",
"skipReason": "unknown_workplace_type",
"job_title": "Product Designer",
"company_name": "Notion",
"URL": "https://wellfound.com/jobs/3390214-product-designer",
"runId": "8f2c1e9a-run",
"scrapedAt": "2026-07-26T14:03:40Z",
"workplaceType": null,
"yearsExperienceMin": null,
"salary": "120K–150K a year"
}

skipReason is one of: unknown_workplace_type / unknown_experience / unknown_salary (the field genuinely wasn't published, only recorded when keepUnspecified is false), unsupported_page_template (the page didn't parse into a title and URL), seed_error (a seed URL threw an exception mid-run, with an errorMessage field attached), or proxy_exhausted (every proxy tier was exhausted for that seed or job without producing a row).

One run_summary row closes out every run:

{
"rowType": "run_summary",
"runId": "8f2c1e9a-run",
"scrapedAt": "2026-07-26T14:10:02Z",
"cardsSeen": 58,
"rowsPushed": 6,
"filterAccounting": { "seen": 58, "kept": 6, "kept_with_unknown": 2, "unparseable": 0, "seed_blocked": 0, "reject_workplace_type": 4, "reject_remote_only": 0, "reject_experience": 9, "reject_min_salary": 12, "reject_excluded_company": 1, "reject_company_filter": 0, "reject_job_type": 0, "reject_date_posted": 0, "unknown_workplace_type": 0, "unknown_experience": 0, "unknown_salary": 0 },
"coverage": { "rowsCaptured": 6, "coverageDenominator": "rows pushed by this run (after filtering)", "workplaceTypeCoverage": "4/6 = 67%", "wfhFlexibleCoverage": "3/6 = 50%", "acceptedRemoteLocationsCoverage": "2/6 = 33%", "yearsExperiencePublishedCoverage": "3/6 = 50%", "yearsExperienceRegexFallback": "1/6 = 17%", "yearsExperienceAnyCoverage": "4/6 = 67%", "isRemoteTrue": "5/6 = 83%", "jobLocationsCoverage": "5/6 = 83%" },
"coverageBeforeFiltering": { "cardsSeen": 58, "workplaceTypeCoverage": "16/58 = 28%", "acceptedRemoteLocationsCoverage": "12/58 = 21%", "yearsExperiencePublishedCoverage": "11/58 = 19%", "yearsExperienceRegexFallback": "4/58 = 7%", "isRemoteTrue": "39/58 = 67%" },
"geoLookups": { "enabled": true, "cap": 20, "used": 6, "succeeded": 6, "withLocations": 5, "blocked": 0, "noLdJson": 1 }
}

filterAccounting mirrors the run's internal counters exactly (seen, kept, kept_with_unknown, unparseable, seed_blocked, every reject_* reason, and every unknown_* reason). coverage reports each role-shape field's real fraction over the rows this run actually pushed; coverageBeforeFiltering reports the same fields over every card the run looked at, before any filter ran — this second figure is the one that reflects Wellfound's true publishing rate. geoLookups reports the location-resolution budget: how many of maxGeoLookups were used, how many succeeded, how many returned coordinates, and how many were blocked or lacked ld+json entirely.

Field names stay stable across runs; a Wellfound front-end change affects extraction logic, not the schema this Actor emits. Results export from the Apify Console or API as JSON, CSV, Excel, XML, or RSS, same as any Apify dataset.

⚠️ Salary Parsing: Exact Formula and Currency Handling

Salary is never split into numeric min/max/currency fields on the output row — it stays a single normalized salary string, and minAnnualSalary filtering happens against a number derived from that string internally, never exposed separately. Here is exactly how both steps work:

  1. Normalizing the display string — Wellfound's raw compensation text is matched against \$([\d,.]+)\s*([kKmM]?)\s*[-–—]\s*\$([\d,.]+)\s*([kKmM]?) for a range. If it matches, the output becomes "{lo}{unit}–{hi}{unit} a year" — e.g. "$100k - $150k" becomes "100K–150K a year". The unit defaults to K when Wellfound's text omits it, and the high bound inherits the low bound's unit if its own is missing. If no range matches, a single \$([\d,.]+)\s*([kKmM]?) value becomes "{value}{unit} a year". If neither pattern matches — most commonly because the text uses a currency symbol other than $ — the raw compensation text is returned unchanged, with no "a year" suffix added.
  2. Deriving the filter numberminAnnualSalary compares against a lower-bound integer extracted from the salary string above (not from Wellfound's raw text) via ([\d,.]+)\s*([kKmM]?), the first number-plus-unit token found. Commas are stripped, and the value is multiplied by 1,000 for a K suffix or 1,000,000 for an M suffix. Because this second regex has no currency-symbol requirement, it can still extract a number from text that fell through step 1 unformatted (for example a euro-prefixed string), as long as a digit-plus-unit pattern is present.
  3. Currency scope — only $-prefixed values are recognized as US-dollar amounts by the display formatter. Postings priced in another currency are not converted or labeled — they pass through as raw text, and the filter step may still parse a number out of them if one is present, without regard to which currency it actually represents. Treat minAnnualSalary as a same-currency filter aid for USD-denominated postings, not a currency-normalized compensation dataset.
  4. Unknown handling — when neither pattern finds a number, the field is reported as unknown for filtering purposes: with keepUnspecified on, the role is kept and "salary" appears in unknownFields; with it off, the role is dropped as an uncharged unknown_salary accounting row.

💡 Wellfound Jobs Scraper Strategy Guide

Three ways teams typically deploy this Actor beyond a one-off search, each runnable with the real inputs and outputs documented above.

Strategy 1: Real-Time Enrichment Pipeline

Trigger a run whenever a new company name enters your CRM or ATS, with companyName set to that record and pagesToFetch left at its default. Read back workplaceType, seniorityBand, and salary for any open roles, and write them onto the CRM record as hiring-signal fields. A workplaceTypeKnown: false result means the enrichment field should be left blank rather than treated as "onsite," since the employer never stated it.

Strategy 2: Scheduled Monitoring and Alerting

Use an Apify Schedule to run the Actor daily against a fixed locationName or includeKeyword, with workplaceTypes: ["REMOTE"] and minAnnualSalary set to your floor. Diff the current run's jobId values against the previous run's dataset, and alert only on jobIds that are new — that is the delta that matters for a "new remote senior roles above $X" watch, rather than re-alerting on roles already seen.

Strategy 3: Bulk Dataset Build

For a market-wide dataset, run the Actor once per target locationName or includeKeyword via the Apify API, in parallel Actor runs, each writing to its own dataset. Aggregate the resulting datasets' items through the Apify API's dataset export (JSON or CSV) into a single warehouse table or CSV for downstream analysis of workplace-type and seniority distribution across the whole seed list. No concurrency ceiling is documented for this Actor, so plan run counts around what your own Apify plan and proxy usage can sustain.

StrategyBest forRun patternOutput format
Real-time enrichmentCRM/ATS hiring-signal enrichmentTriggered single run per companyDataset row read back via API
Scheduled monitoringNew-role alerting on a fixed searchApify Schedule, diffed on jobIdDataset, diffed run-over-run
Bulk dataset buildMarket-wide research datasetParallel runs, one per seedAggregated CSV or warehouse table

Other Wellfound-focused Actors cover different parts of the same listings, and one Scrapio Actor covers the same job-listing entity on LinkedIn instead:

ScraperWhat it extracts
Wellfound Jobs ScraperThe standard Wellfound listing fields this variant builds on: title, company, location, remote flag, salary text, job type, posting age.
Wellfound Jobs & Startup Company Profile ScraperEmployer firmographics per hiring company — employee-size band, tagline, logo, funding stage, and investor badges.
Wellfound Jobs Scraper With ATS Vendor & Hiring VelocityThe employer's recruiting stack — ATS vendor, company website, exact posting timestamp, and job age.
Wellfound Jobs Scraper — Salary Breakdown & BenefitsNumeric salaryMin/salaryMax/currency/period parsed from the posting's own pay block, plus benefit tags and equity clauses.
LinkedIn Jobs Scraper: Exact Posting Dates & RepostsThe same job-listing entity on LinkedIn, with exact posting dates and repost/duplicate grouping.

Integrate the Wellfound Jobs Scraper With Your Stack

This Actor works with any language or tool that can make an HTTP request, through the Apify API or the official client libraries. Both scripts below call the Actor and export the results to CSV.

Python

import csv
from apify_client import ApifyClient
client = ApifyClient("<YOUR_APIFY_TOKEN>")
run_input = {
"locationName": "New York",
"workplaceTypes": ["REMOTE", "HYBRID"],
"experience": "senior",
"minAnnualSalary": 150000,
"pagesToFetch": 2,
}
run = client.actor("<YOUR_USERNAME>/wellfound-jobs-scraper-by-remote-seniority-salary-filter").call(
run_input=run_input
)
rows = list(client.dataset(run["defaultDatasetId"]).iterate_items())
jobs = [r for r in rows if r.get("rowType") == "job"]
with open("wellfound_jobs.csv", "w", newline="", encoding="utf-8") as f:
fieldnames = [
"job_title", "company_name", "workplaceType", "seniorityBand",
"salary", "isRemote", "location", "URL",
]
writer = csv.DictWriter(f, fieldnames=fieldnames, extrasaction="ignore")
writer.writeheader()
writer.writerows(jobs)
print(f"Saved {len(jobs)} job row(s) to wellfound_jobs.csv")

Node.js

import { ApifyClient } from "apify-client";
const client = new ApifyClient({ token: "<YOUR_APIFY_TOKEN>" });
const run = await client.actor("<YOUR_USERNAME>/wellfound-jobs-scraper-by-remote-seniority-salary-filter").call({
locationName: "New York",
workplaceTypes: ["REMOTE", "HYBRID"],
experience: "senior",
minAnnualSalary: 150000,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
const jobs = items.filter((r) => r.rowType === "job");
console.log(`Fetched ${jobs.length} job row(s)`);
jobs.forEach((j) => console.log(j.job_title, j.company_name, j.salary));

Async and Scheduled Pipelines

For large or recurring jobs, don't wait synchronously on the run: use client.actor(...).start() to fire the Actor asynchronously and poll the run status, or read the resulting dataset once it finishes. For recurring monitoring, set up an Apify Schedule against this Actor with a fixed input, and pull the new dataset via the API each time the schedule fires rather than diffing inside the run itself.

Who Needs This Wellfound Scraper? (Use Cases & Industries)

The audiences below match the ones in the section above — same list, applied here to specific outcomes rather than general workflows.

Recruiters and Talent Sourcing Teams

A recruiter sets experience: "senior" and minAnnualSalary: 150000 against a target city and gets back only roles matching both, with unknownFields flagging any that didn't state salary so they aren't mistaken for a rejection.

Compensation and People Analytics Teams

An analyst pulls salary, seniorityBand, and company_name across a metro area to build a rough external benchmark of what startups are advertising for a given seniority band, refreshed on a schedule.

Startup Market Intelligence and VC Research

A researcher tracks which companies are actively posting REMOTE or HYBRID roles above a salary floor as a proxy for hiring momentum and funding health across a sector.

Researchers

🔬 Academic and labor-market researchers use the workplace-type and experience fields, each tagged with its real coverage rate, to study remote-work adoption trends without over-claiming universal coverage. Scope is limited to publicly visible listing data.

Job Board and Directory Builders

A team building a filtered remote-jobs directory ingests workplaceType, seniorityBand, salary, and jobLocations directly into their product's listing schema, without writing their own Wellfound parser.

Scraping publicly accessible web pages is generally lawful in the United States: in hiQ Labs, Inc. v. LinkedIn Corp. (9th Cir. 2019), the court held that scraping data a website makes available to the public, without bypassing an access control, does not violate the Computer Fraud and Abuse Act. That precedent concerns unauthorized-access law, not a website's own terms of service — violating Wellfound's Terms of Service in the course of scraping is a separate matter, one of civil contract risk between the scraper and Wellfound rather than a criminal one. This Actor extracts job-listing and employer-name data — business records, not personal profiles about individuals — so data-protection frameworks built around personal data (GDPR, CCPA) generally do not attach to its output the way they would to a scraper of individual user profiles.

This Actor returns only publicly accessible data. What you do with that data is your responsibility — consult legal counsel for commercial applications, and review Wellfound's Terms of Service before large-scale or repeated use.

❓ Frequently Asked Questions

Does this Actor work without a Wellfound account?

Yes. It reads only public search, listing, and job-detail pages — no Wellfound login, cookies, or session token is required, and the input schema has no credential or API-key field at all.

How does it handle Wellfound's anti-scraping measures?

It runs a stealth browser (Camoufox) behind Apify's proxy network, defaulting to residential sticky sessions since Wellfound's DataDome anti-bot layer reliably blocks datacenter and direct connections from cloud IP ranges. On a block it escalates through no-proxy → datacenter → residential tiers and rotates to a fresh session ID, retrying up to three times per seed before giving up and recording an uncharged proxy_exhausted row. Detail-page location lookups run strictly one at a time, with a delay that grows after each block and a circuit breaker that pauses geo resolution for the rest of the run after four consecutive blocked pages.

What happens if my search returns zero results?

The run still completes and pushes an uncharged run_summary row with rowsPushed: 0, so a zero-result run is distinguishable from a failed one. Common causes are a location or role keyword with no current matches, or filters (workplace type, experience band, salary floor) narrower than what's currently posted — loosen workplaceTypes, experience, or minAnnualSalary, or turn keepUnspecified on to stop dropping roles that simply don't state a filtered field.

Can I run this at scale without getting blocked?

The Actor's own retry and proxy-escalation logic is designed to recover from individual blocks automatically, and requestDelay (with jitter) can be raised if Wellfound starts serving anti-bot stubs more often. No uptime or success-rate figure is published for this Actor, so plan for occasional proxy_exhausted or blocked outcomes on individual seeds or job pages rather than assuming a guaranteed completion rate.

How fresh is the data this Actor returns?

Every run performs a live fetch of Wellfound's current pages at the time it runs — nothing is cached or served from a prior run. scrapedAt on every row records exactly when that fetch happened.

Which fields work best for AI training and RAG indexing?

description is the high-information text field for RAG indexing. For training data, workplaceType, seniorityBand, job_type, and salary are the most consistently structured fields, each normalized to a small fixed vocabulary. Every field returns as a typed primitive — string, boolean, integer, or array — requiring no normalization before use in an LLM context window.

Does this data include personal information about job applicants or employees?

No. Output rows describe job postings and hiring companies — titles, salary text, workplace type, company names — not individual applicants, employees, or candidates. Lawful basis for storing and using any data you collect still sits with you as the operator of the run.

Does this work with Claude, ChatGPT, and other AI agent tools?

It has no dedicated MCP server integration documented. It is callable as a standard HTTP endpoint through the Apify API by any agent framework capable of making a tool call — every response is typed JSON, requiring no HTML parsing before it's passed into an LLM context window.

How does this compare to other Wellfound scrapers?

Against khadinakbar's Wellfound Jobs Scraper (observed 2026-07-26): that Actor documents split numeric salaryMin/salaryMax/salaryCurrency and equity fields plus a SerpApi-based fallback discovery method, neither of which this Actor implements; this Actor instead documents workplace-type classification from a real Wellfound field, an auditable seniority band, structured job geo, and uncharged accounting rows for filtered-out unknowns, none of which appear on that competitor's listing. Against abotapi's Wellfound Jobs Scraper (observed 2026-07-26): that Actor documents company badge signals (funding, hiring-status, investor badges) and an optional connector export to Notion/Airtable, which this Actor does not attempt; this Actor's role-shape filtering and coverage auditing are not documented on that listing.

Disclaimer

This Actor extracts only publicly available data from Wellfound. It is intended for lawful use cases only. Users are responsible for complying with Wellfound's Terms of Service and applicable data protection laws in their jurisdiction.