Wellfound Jobs Scraper — Salary Breakdown & Benefits avatar

Wellfound Jobs Scraper — Salary Breakdown & Benefits

Under maintenance

Pricing

from $4.99 / 1,000 results

Go to Apify Store
Wellfound Jobs Scraper — Salary Breakdown & Benefits

Wellfound Jobs Scraper — Salary Breakdown & Benefits

Under maintenance

Scrape job listings from Wellfound (formerly AngelList Talent) at scale. Search by location, company, keyword, or paste raw URLs.

Pricing

from $4.99 / 1,000 results

Rating

0.0

(0)

Developer

API Empire

API Empire

Maintained by Community

Actor stats

0

Bookmarked

1

Total users

0

Monthly active users

16 days ago

Last modified

Share

Wellfound Jobs Scraper — Salary, Equity and Benefits as JSON

Wellfound Jobs Scraper pulls startup job listings from Wellfound (formerly AngelList Talent) and returns each posting as three linked data types: the job listing itself, its parsed pay band, and its structured benefits list. Salary numbers come from the job page's own schema.org baseSalary object — not a regex guess over a "175K-275K" label — so every salaryMin/salaryMax/salaryCurrency/salaryPeriod traces back to what the employer actually published. Every response is typed, normalized JSON: no HTML, no CSS selectors, no parsing step. Point it at a market, a role, a single employer, or a list of Wellfound URLs, and you get back a dataset you can filter by pay range before you ever open it.

What is Wellfound Jobs Scraper — Salary Breakdown & Benefits?

It is an Apify Actor that scrapes Wellfound job search results and individual job pages, and splits each posting's compensation block into machine-readable fields instead of leaving it as one display string. No Wellfound account or login is required — the Actor only reads pages that are publicly visible to any visitor. It runs a real (headless by default) browser under the hood, so it also handles Wellfound's JavaScript-rendered listings and its DataDome anti-bot layer without you managing any of that yourself.

  • Scrape job listings by market, role, employer, or a pasted list of Wellfound URLs
  • Get exact salary bands (salaryMin, salaryMax, salaryCurrency, salaryPeriod) parsed from the posting's own published pay object
  • Get the equity clause and the full benefits list, split into tags when Wellfound's own text is a tag list
  • Filter the whole run on real salary numbers, not keyword matches, before you're billed for a row
  • Export as JSON, CSV, Excel, XML or RSS straight from the Apify dataset — no parsing on your end

What data does Wellfound Jobs Scraper collect?

The dataset carries three distinct data types in the same run: the job listing, its parsed pay band, and its benefits/equity block. A single charged row merges all three; two additional uncharged row types (skipped, error) and one run-level summary row (run_summary) ride alongside them for auditability.

Data TypeKey FieldsJSON Field Names
Job listingtitle, company, location, employment type, posting age, descriptionjob_title, company_name, location, job_type, date, description, URL
Pay bandexact min/max, currency, pay period, provenance of the numbersalaryMin, salaryMax, salaryCurrency, salaryPeriod, salarySource, salaryDisclosed
Benefits & equitystructured benefit tags or raw prose, benefit count, equity clausebenefits, benefitsRaw, benefitsParsed, benefitCount, equityOffered
Run coveragejobs sampled, jobs charged, disclosure and tagging rates, filter breakdownsampleSize, rowsCharged, payDisclosureRate, benefitsTaggedRate, filteredOut, filteredNoSalary

The date field on a job row is Wellfound's own relative text ("3 days ago", "today"), passed through unchanged — it is not normalized into an absolute timestamp. If you need an absolute time, use scrapedAt (the moment the Actor captured the row) as your anchor, not date.

Need more Wellfound data?

This variant deliberately keeps its scope to pay and benefits — it does not collect company size, startup badges, remote-work configuration, years-of-experience requirements, or ATS/auto-post metadata, because those are the focus of sibling Wellfound Actors published under API Empire. If your workflow needs company firmographics alongside the pay data, run this Actor for compensation and pair it with a company-profile-focused Wellfound scraper for the rest.

💰 How salary, equity and benefits actually get parsed

This is the part every "salary scraper" gets vague about, so here is the exact rule.

Salary — two sources, ranked, never blended. The primary source is the baseSalary object inside the schema.org JobPosting block that Wellfound embeds as <script type="application/ld+json"> on the job's own detail page (only there — the search-results page does not carry it). The Actor reads baseSalary.value.minValue, .maxValue, .currency (falling back to .currencyCode, then to value.currency), and .unitText, and normalizes the unit onto a fixed vocabulary (YEAR, MONTH, WEEK, DAY, HOUR); an unrecognized unit is passed through as-is rather than dropped. If baseSalary is a bare number instead of an object, both salaryMin and salaryMax are set to that value. Every number is rounded to the nearest integer, and if the parsed minimum somehow exceeds the maximum the two are swapped defensively.

The fallback — used only when the detail page wasn't fetched (fetchPayDetails=false) or carried no baseSalary — is a regex ported from a sibling Wellfound Actor, run against the listing card's own compensation text (e.g. "$100k – $137k • No equity"): [\$€£₹¥]([\d,.]+)\s*([kKmM]?)\s*[-–—]\s*[\$€£₹¥]?([\d,.]+)\s*([kKmM]?). It multiplies k/m suffixes, strips thousands separators, and — because Wellfound always renders listing-card compensation as an annual figure — defaults the period to YEAR when no unit is otherwise known. Currency in this fallback path comes from a symbol table ($→USD, →EUR, £→GBP, →INR, ¥→JPY, C$→CAD, A$→AUD) or a bare 3-letter ISO code found in the text.

Every row carries salarySource so you can audit which path produced the number: published_ldjson, parsed_from_compensation_text, or none.

Equity is pulled by extract_equity() from the same listing-card compensation string, split on /·/|. It returns the first segment that contains the word "equity" verbatim, or a bare leading percentage range (Wellfound's shorthand for a "0.10% – 0.50%" equity band with no explicit label). It is never invented — most Wellfound postings carry no equity statement at all, and those return null.

Benefits come from the jobBenefits string in the same ld+json block, split on -, , ·, ;, |, or newlines. The split is only trusted as a tag list if every resulting segment reads like a tag (six words or fewer, 60 characters or fewer, no internal sentence punctuation); if even one segment reads as a sentence, nothing is tagged and the whole string is kept as benefitsRaw with benefitsParsed: false. This is deliberately all-or-nothing per posting — it will not half-tag a benefits block.

Known failure modes, read straight from the code, not measured:

  • equityOffered is read only from the listing card's compensation text, never from the job-detail ld+json block. A posting can have salarySource: "published_ldjson" (a fully successful detail fetch) and still return equityOffered: null, simply because the listing card's blurb didn't carry an equity clause.
  • salaryCurrency can be null even when salaryMin/salaryMax are populated, if Wellfound's baseSalary object omits currency, currencyCode, and value.currency all at once.
  • The plain-text salary field (e.g. "175K–275K a year") is a cosmetic reformat of the listing card's raw compensation text via a separate, looser regex — it does not read the ld+json numbers, so it can visually disagree with the authoritative salaryMin/salaryMax when the detail page supplied a more precise figure than the card blurb.
  • When a posting discloses only one bound (a fixed number, not a range), both salaryMin and salaryMax are set to that same value — there is no way to tell "exactly $150,000" apart from "$150,000, no stated ceiling" downstream.

Why not build this yourself?

Wellfound does not publish a general-purpose jobs API, so the only way to get this data is to read the pages Wellfound renders for a browser — and that means dealing with three moving parts directly. First, Wellfound's job-detail pages are Rails-rendered and ship no __NEXT_DATA__ script at all; only the search/listing pages carry that marker. A scraper that gates page-readiness on __NEXT_DATA__ — a natural first attempt — will misjudge every successfully-loaded detail page as blocked, because that marker's absence there is normal, not a failure signal. Second, Wellfound's Apollo GraphQL cache shape has changed at least once in this Actor's own history (entities moved one level deeper, under an added .data key), silently breaking company-name and location extraction for every row until the extractor was updated to match. Third, Wellfound sits behind DataDome: direct and datacenter-IP requests are reliably blocked, job-detail pages return small challenge stubs when hit in a burst, and a working scraper needs sticky residential sessions, IP rotation on block, and backoff logic — not just a single retry.

The Actor's own proxy manager formalizes that third problem as three tiers — none, datacenter, residential — and starts at residential by default (with a fresh sticky session per retry) precisely because the other two tiers reliably fail against Wellfound's DataDome. If you supply your own proxyConfiguration, the tier it implies is honored instead; either way, a block escalates the tier one step and retries, up to three residential-tier attempts per seed URL before the Actor gives up on that seed and logs an uncharged proxy_exhausted error row rather than charging you for a partial or empty result. Maintaining all of this yourself means re-discovering each of these three problems the hard way, in production, the same way this Actor's own changelog did.

Why do developers and teams scrape Wellfound pay data?

For compensation analysts and recruiters

Wellfound is one of the few large job boards where a meaningful share of startup postings publish an exact number instead of "competitive salary." Pull every listing for a role and market (payLocation + roleKeyword), keep only postings with salaryDisclosed: true, and you have a real, sourced pay-band sample for that segment — company name, exact band, currency and equity clause per row — without touching a single job posting by hand.

For AI engineers and agent builders

Because every field is typed JSON with stable key names, a compensation-lookup agent can call this Actor as a tool, filter the returned rows on salaryMin/salaryMax, and pass the result straight into an LLM context or a RAG index — no HTML parsing step sits between the scrape and the model. The minSalary/maxSalary/includeNoSalary inputs let an agent constrain the search itself, so it isn't fetching and then discarding rows it doesn't need.

For labour-market researchers

postedWindow, roleType, and the run-level payDisclosureRate in the run_summary row make it possible to track how much of a market actually discloses pay over time, not just what the disclosed numbers are — useful for studying the effect of pay-transparency norms on a startup-heavy labour segment specifically.

For developers building data products

The emitSkippedRows and run_summary rows mean a pay-benchmarking product built on top of this Actor can show its own coverage honestly ("8 of 100 postings in this market disclosed pay this week") instead of silently presenting a biased sample as complete.

🧭 How to scrape Wellfound salaries (step by step)

  1. Open Wellfound Jobs Scraper — Salary Breakdown & Benefits on its Apify Store listing and click Try for free (or Run, if you've already added it).
  2. No input is required — every field has a default. To target a specific pay sample, set payLocation (e.g. "San Francisco") and/or roleKeyword (e.g. "backend engineer"), or paste specific Wellfound URLs into startUrls.
  3. Narrow the sample with roleType, postedWindow, minSalary/maxSalary, and employerName if you only want one company's listings.
  4. Click Start and watch the run log — it prints the pay filter, the listing pages per seed, and whether the pay/benefits lookup is on.
  5. Download the finished dataset as JSON, CSV, Excel, XML or RSS from the Storage tab, or pull it programmatically with the Apify API/SDK.

What to do when Wellfound changes its structure

This Actor reads Wellfound's data through two independent channels — the embedded Apollo GraphQL cache for listings, and the schema.org ld+json block for job-detail pay data — precisely because relying on rendered DOM markup alone breaks on every visual redesign. It has already absorbed one real Wellfound cache-nesting change without a schema break for end users (see the changelog). Field names and types on your side stay stable across maintenance updates; no specific turnaround time is promised for any given break.

⬇️ Input

No parameter is required — every field has a default, and an empty input run falls back to Wellfound's generic /jobs landing page.

ParameterRequiredTypeDescriptionExample Value
startUrlsNoarrayWellfound search/listing URLs or individual job page URLs. Takes priority over the search fields below. Default [].["https://wellfound.com/role/r/software-engineer"]
payLocationNostringCity or region to benchmark, e.g. "New York", "San Francisco", "Remote". Builds the Wellfound search URL when no startUrls are given. Default "New York"."San Francisco"
roleKeywordNostringRole, title or skill to narrow the pay sample. Default ""."backend engineer"
employerNameNostringRestrict the sample to one employer — a loose, normalized substring match against the company name on each card. Default ""."Notion"
listingPagesToScanNointegerResult pages to walk per URL. Minimum 1, maximum 100. A page carries roughly 50 job cards per the Actor's own input description. Default 1.3
maxItemsNointegerHard cap on charged job rows across all URLs. 0 = no cap. Minimum 0. Default 0.100
minSalaryNointegerKeep only postings whose published band reaches at least this amount (own currency/period). 0 = off. Minimum 0. Default 0.150000
maxSalaryNointegerKeep only postings whose band starts at or below this amount. 0 = off. Minimum 0. Default 0.220000
includeNoSalaryNobooleanKeep postings with no published pay (salaryMin/salaryMax stay null, never guessed). Default true.true
roleTypeNostring (enum)Employment type filter. One of "" (Any type), FULLTIME, PARTTIME, CONTRACTOR, INTERN. Default ""."FULLTIME"
postedWindowNostring (enum)Posting-age filter. One of all, today, 3days, week, month. Default "all"."week"
fetchPayDetailsNobooleanOpen each job's detail page to read its baseSalary/jobBenefits ld+json block — the only place the exact numbers and benefits text live. Turning this off falls back to the compensation-text parser. Default true.true
detailPageDelayNonumberPause, in seconds, before each job-detail page load. Minimum 0, maximum 30. Default 2.2
fetchDescriptionsNobooleanInclude the job description text. Setting this to false also disables the pay/benefits lookup unless fetchPayDetails is set explicitly. Default true.true
emitSkippedRowsNobooleanWrite an uncharged type: "skipped" row for every posting your pay filters removed. Default true.true
requestDelayNonumberPause, in seconds, before each search-results page load. Minimum 0, maximum 30. Default 1.1
headlessNobooleanRun the browser headless. Default true.true
countryNameNostring (enum)Proxy exit country (249 supported, per the Actor's own input description). Geo-targets the connection only — it does not filter which jobs are returned. Default "United States"."United States"
proxyConfigurationNoobjectApify Proxy configuration used for both search and job pages. Default {"useApifyProxy": false}.{"useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"]}

⚠️ The most common input mistake is turning off fetchDescriptions without checking fetchPayDetails. Because fetchPayDetails inherits fetchDescriptions's value when you don't set it explicitly, {"fetchDescriptions": false} alone silently disables the pay/benefits lookup too — every row falls back to salarySource: "parsed_from_compensation_text" instead of the exact published numbers. Set fetchPayDetails: true explicitly if you want descriptions off but exact pay on.

⚠️ If you're building raw JSON input by hand (e.g. via the API rather than the Console form), stick to the parameter names in the table above. Internally, several fields also accept an older, undocumented alias inherited from a sibling Actor's input shape (for example locationName instead of payLocation, companyName instead of employerName, jobType instead of roleType, datePosted instead of postedWindow, pagesToFetch instead of listingPagesToScan, jobUrls instead of startUrls). When both an alias and its documented equivalent are present in the same input JSON, the alias wins silently — there is no warning in the run log. This only matters if you assemble input programmatically from another Actor's template; the Console form only ever writes the documented names.

Example input:

{
"startUrls": [],
"payLocation": "San Francisco",
"roleKeyword": "backend engineer",
"employerName": "",
"listingPagesToScan": 3,
"maxItems": 100,
"minSalary": 150000,
"maxSalary": 220000,
"includeNoSalary": true,
"roleType": "FULLTIME",
"postedWindow": "week",
"fetchPayDetails": true,
"detailPageDelay": 2,
"fetchDescriptions": true,
"emitSkippedRows": true,
"requestDelay": 1,
"headless": true,
"countryName": "United States",
"proxyConfiguration": { "useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"] }
}

⬆️ Output

Every run writes to one Apify dataset, but not every row is a job. Four row shapes ride together, distinguished by type; only type: "job" rows are ever billed.

Scraped job (type: "job")

The default Store view shows 19 columns, but the row itself carries 25 fields — posted_via, jobId, detailPageParsed, salaryDisclosed, description and scrapedAt are written to every job row but are only visible in the dataset's Full Details view or via the API/CSV export.

{
"type": "job",
"job_title": "Senior Backend Engineer",
"company_name": "Acme Robotics",
"location": "San Francisco, CA",
"posted_via": "Wellfound",
"salary": "175K–225K 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": "Acme Robotics is hiring a senior backend engineer to own our fleet-control API...",
"compensationRaw": "$175k – $225k • 0.05% – 0.15%",
"salaryMin": 175000,
"salaryMax": 225000,
"salaryCurrency": "USD",
"salaryPeriod": "YEAR",
"salarySource": "published_ldjson",
"salaryDisclosed": true,
"equityOffered": "0.05% – 0.15%",
"benefitsRaw": "Health Insurance - Dental Insurance - 401K Plan - Unlimited PTO",
"benefits": ["Health Insurance", "Dental Insurance", "401K Plan", "Unlimited PTO"],
"benefitsParsed": true,
"benefitCount": 4,
"detailPageParsed": true,
"jobId": "3324973",
"scrapedAt": "2026-07-25T14:02:11Z"
}

Uncharged accounting rows

A run also writes rows that document what didn't become a job — none of these are billed.

type: "skipped" — a posting your pay filters removed (errorReason is one of no_salary_disclosed, below_min_salary, above_max_salary):

{
"type": "skipped",
"errorReason": "below_min_salary",
"job_title": "Junior Support Engineer",
"company_name": "Acme Robotics",
"URL": "https://wellfound.com/jobs/3324980-junior-support-engineer",
"salaryMin": 65000,
"salaryMax": 85000,
"charged": false,
"scrapedAt": "2026-07-25T14:02:40Z"
}

type: "run_summary" — one row per run, written once at the end, giving coverage over the whole sample (the runSummary view shows 20 of its 22 fields; runId and charged are dataset-only):

{
"type": "run_summary",
"runId": "a1b2c3d4e5f6g7h8i9",
"sampleSize": 100,
"rowsCharged": 63,
"detailPagesAttempted": 100,
"detailPagesParsed": 91,
"detailParseRate": 0.91,
"payDisclosureRate": 0.78,
"publishedSalaryRate": 0.72,
"textParsedSalaryRate": 0.06,
"benefitsPresentRate": 0.54,
"benefitsTaggedRate": 0.41,
"benefitsProseCount": 13,
"equityDisclosureRate": 0.09,
"filteredOut": 37,
"filteredNoSalary": 22,
"filteredBelowMin": 11,
"filteredAboveMax": 4,
"detailPagesThrottled": 6,
"detailPagesNavFailed": 3,
"charged": false,
"scrapedAt": "2026-07-25T14:05:02Z"
}

type: "error" rows carry only type, errorReason, URL, charged: false and scrapedAterrorReason is one of unsupported_page_template (page didn't match any known template), proxy_exhausted (all proxy-tier retries failed for a seed), seed_failed (an unexpected exception on one seed URL), or blocked (a single detail URL couldn't be retrieved after retries).

How does Wellfound Jobs Scraper compare to other Wellfound scrapers?

FeatureWellfound Jobs Scraper — Salary Breakdown & BenefitsGeneric alternative
Salary sourceJob page's own schema.org baseSalary object, with the parsing method reported per row (salarySource)Usually a single regex over listing-card text, provenance not reported
BenefitsTag list or raw prose, decided per posting — never half-taggedOften a flat string or omitted
Filtered-out rowsWritten as uncharged skipped rows with a reason, so a filtered run is auditablethirdwatch/wellfound-jobs-scraper's listing does not document a skipped-row concept (checked on the Apify Store, 2026-07-25)
Run-level coveragerun_summary row reports pay-disclosure and benefits-tagging rates for the whole sampleNot documented on either competing Wellfound listing (checked 2026-07-25)
Login requirementNone — public pages onlykhadinakbar/wellfound-jobs-scraper likewise documents no login required (checked 2026-07-25); thirdwatch/wellfound-jobs-scraper offers an optional session cookie "for higher reliability on heavy runs" (checked 2026-07-25)

If you're building an AI agent or RAG pipeline, the row-level salarySource field is the decision-maker — an agent that can tell "exact published number" apart from "regex guess" can weight or discard rows accordingly, instead of treating every salary figure as equally reliable.

How many jobs can you scrape with Wellfound Jobs Scraper?

There is no hard cap in the Actor itself — maxItems defaults to 0, meaning unlimited, and stops the run only once you set it. listingPagesToScan is capped at 100 pages per seed URL by the input schema; each listing page carries roughly 50 job cards per the schema's own description, so 100 pages is on the order of 5,000 candidate postings per seed before your pay filters run. Wellfound itself imposes one real limit worth knowing: its generic /jobs?location=<slug> query-string search is not a real paginated search — it silently serves a landing page hard-capped at roughly 49 featured cards with no further pages. This Actor avoids that trap by building /location/<slug> URLs instead, which are genuinely paginated.

The other practical ceiling is on detail-page enrichment, not listings: if three consecutive job-detail loads come back as anti-bot throttle stubs or navigation failures, the Actor pauses for 30 seconds and retries; a second run of three consecutive failures pauses for 60 seconds; a third run of three consecutive failures permanently disables published pay/benefit lookup for the rest of that run. Listing-page fields (title, company, location, type, date) are unaffected — only salarySource falls back to parsed_from_compensation_text and benefits/equityOffered extraction stops for any job not yet processed. No benchmark run time is published here — none has been measured for this documentation.

Integrate Wellfound Jobs Scraper and automate your workflow

Wellfound Jobs Scraper works with any language or tool that can send an HTTP request, through the standard Apify API.

REST API integration

from apify_client import ApifyClient
client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("<YOUR_USERNAME>/wellfound-jobs-scraper-salary-breakdown-benefits").call(
run_input={
"payLocation": "San Francisco",
"roleKeyword": "backend engineer",
"minSalary": 150000,
"fetchPayDetails": True,
}
)
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
if item.get("type") == "job":
print(item["job_title"], item["salaryMin"], item["salaryMax"], item["salaryCurrency"])

Works in Python, Node.js, Go, Ruby, and cURL — the call shape is the same Apify Actor-run API for every client.

Automation platforms (n8n, Make, LangChain)

Apify's official n8n node and Make app can both start this Actor with a fixed input object and read the resulting dataset back into your workflow, without writing any HTTP code. A LangChain or similar agent framework can wrap the same apify_client call shown above as a tool function, passing payLocation/roleKeyword/minSalary as the tool's arguments and filtering the returned items on type == "job".

Yes — this Actor collects only data that is publicly visible on Wellfound without logging in. Job postings are business/product listings, not personal data about a private individual, so the operative framework is Wellfound's own Terms of Service and database-rights law in your jurisdiction, not GDPR or CCPA. You are responsible for using the data in line with Wellfound's terms and any applicable law in your jurisdiction, particularly around reuse, redistribution, and rate of access. Consult legal counsel for commercial use cases, especially any that involve bulk collection or downstream use of company or personal identifiers found inside job descriptions.

❓ Frequently asked questions

Does Wellfound Jobs Scraper work without a Wellfound account?

Yes. No login, cookie, or credential input exists in this Actor's schema — it reads only pages any visitor can open.

How often is the scraped data updated?

Every run fetches Wellfound live at request time. Nothing is cached between runs; re-running with the same input re-scrapes current listings.

What happens if a job posting doesn't publish a salary?

By default (includeNoSalary: true) it's still returned, with salaryMin/salaryMax left null — never guessed or backfilled. Set includeNoSalary: false to get a pay-transparency-only dataset; excluded postings are still written as uncharged skipped rows with errorReason: "no_salary_disclosed" when emitSkippedRows is on, so you can see what was left out and why.

Can I scrape private or restricted Wellfound content?

No. Only publicly accessible job listings and search pages are returned — there is no path in this Actor for candidate accounts, recruiter dashboards, or messages.

Can I restrict a run to a single employer?

Yes — set employerName. Matching is a loose, normalized substring comparison against the company name shown on each job card (punctuation and case are stripped before comparing), so "acme" matches "Acme Robotics, Inc.". It does not require an exact match, but it also can't distinguish two differently-named subsidiaries that both contain your search term.

Is the date field an absolute timestamp I can sort by?

No — date is Wellfound's own relative label ("3 days ago", "today") copied through unchanged, so it drifts as time passes and can't be sorted reliably after the fact. scrapedAt is the one absolute UTC timestamp on every row (the moment the Actor captured it), and postedWindow on the input side lets you filter by posting age at scrape time instead.

Does maxItems cap billing, or just the number of returned rows?

It caps charged job rows directly — the run stops pulling new listings once the number of charged rows reaches maxItems. Uncharged skipped/error/run_summary rows aren't separately capped, but because the run stops scraping once the cap is hit, you won't see a large batch of them appear after it.

Does Wellfound Jobs Scraper work for AI agent workflows and LLM pipelines?

Yes. It's callable as a standard HTTP endpoint through the Apify API by any agent framework — see the integration example above. Every response is typed JSON with stable field names, so no parsing step sits between the scrape and an LLM context window or vector store.

How does Wellfound Jobs Scraper handle Wellfound's anti-bot system?

It defaults straight to residential proxy sessions with a fresh sticky IP on every retry, because direct and datacenter-IP requests are reliably blocked by Wellfound's DataDome layer. On a detail-page block (detected by response size — a DataDome stub is under 8 KB against a real job page's 60–90 KB) it backs off for 30 then 60 seconds; if job pages are still throttled after both backoffs, published pay/benefit lookup turns off for the rest of that run and salary falls back to the compensation-text parser, while listing-page fields keep coming through unaffected.

How does Wellfound Jobs Scraper compare to other Wellfound scrapers?

Both competing Wellfound listings on the Apify Store — thirdwatch/wellfound-jobs-scraper and khadinakbar/wellfound-jobs-scraper — document salary and equity extraction (checked 2026-07-25), but neither documents reporting how a given number was derived, nor an uncharged skipped-row mechanism for filtered-out postings. This Actor exposes both via salarySource and type: "skipped" rows.

Does Wellfound Jobs Scraper return data in a format LLMs can use directly?

Yes. Typed, normalized JSON with stable field names — no HTML, no selectors, no cleanup pass required before passing rows to a model.

Can I use Wellfound Jobs Scraper without managing proxies?

Yes. It defaults to Apify residential proxy sessions automatically — proxyConfiguration only needs to be set if you want to override that default with your own proxy groups.

What happens when Wellfound changes its structure or blocks the scraper?

The Actor is maintained, and the output schema stays stable on your end — field names and types don't change without notice. No specific turnaround time is promised for any given fix.

💬 Your feedback

Found a bug, or need a field this Actor doesn't collect? Open an issue from the Issues tab on this Actor's Apify Console page — that's the fastest way to reach the maintainer, and it helps everyone else running the same Actor see what's already been reported.