Hacker News Who is Hiring Scraper: Jobs, Emails & Salary
Pricing
from $4.00 / 1,000 job posts
Hacker News Who is Hiring Scraper: Jobs, Emails & Salary
Scrape Hacker News "Who is hiring?" threads into clean rows: company, domain, roles, tech stack, remote, Latin America eligibility, salary, visa, contact emails and apply links. One row per post or per company. Optional email pattern with MX check.
Pricing
from $4.00 / 1,000 job posts
Rating
0.0
(0)
Developer
Oswaldo Carabano
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
22 days ago
Last modified
Categories
Share
Hacker News Who is Hiring Scraper: Jobs, Emails, Salary & LATAM
Turn the monthly Hacker News "Ask HN: Who is hiring?" thread into clean rows you can
export to CSV, JSON or Excel: an HN jobs API alternative with no API key, no login and no browser.
Every company post becomes one row with the company, its domain, the roles, the
tech stack, remote or on-site, where remote hires can be, Latin America
eligibility, the salary range and currency, visa sponsorship, contact emails and
apply links, plus the full text. Optionally, get the company email pattern
(for example first.last@) with its mail servers checked by DNS.
Or switch Output to companies and get one row per hiring company instead:
every post the company made in the months you choose, merged into one deduplicated
row (months it hired, all roles, stack, salary range, contact emails, apply links).
- Every month since April 2011: 184 monthly hiring threads, about 93,700 company posts in total.
- Parsed, not just copied: salary as numbers with currency and period, remote regions, LATAM eligibility with its evidence, de-obfuscated emails (
name [at] company [dot] com). - Built for job seekers writing directly to companies, recruiters mapping who is hiring, and anyone tracking startup hiring and pay.
- Posts or companies: one row per post, or one row per company with all its posts aggregated (
outputType). - $0.004 per post, or $0.01 per company. You never pay for an error row or a duplicate.
What people use it for
| If you are… | You get |
|---|---|
| A developer looking for a remote job | posts that are remote, where remote hires can be, time zones, salary and the apply link |
| A developer in Latin America | latamOnly: posts with a positive signal that LATAM candidates can apply, and the evidence for each one |
| Writing to the hiring team directly | the company domain, its published contact emails, and the email pattern of the domain with MX records |
| Researching startup salaries | salary min / max / currency / period for every band a post lists, equity, seniority |
| Tracking who is hiring month by month | company, domain, Y Combinator batch, funding stage and roles across any months since 2011 |
| Building an outreach list of hiring companies | outputType: companies: one deduplicated row per company, with the months it hired and how many posts it made |
| Building a job board or newsletter | structured rows plus the original text and HTML of every post |
What actually arrives in a row
A post row has 64 fields. The rates below were measured on 1 Oct 2026 over the four latest monthly threads (July to October 2026, n = 848 company posts). We do not promise a field we have not measured.
Always there (100%)
postId · postUrl · storyTitle · month · threadType · author ·
postedAt · headerLine · rawText · rawHtml · scrapedAt
Parsed from the post
| Field | Filled | What it is |
|---|---|---|
company | 91% | from the first line, "Company: …" or "At X we are hiring" |
domain | 80.8% | company domain, from its website, a careers subdomain or a corporate email |
companyUrl | 70% | first link that is not a job board, social network or document |
roles | 76% | role titles from the first line, role lists and bullets |
employmentTypes | 70% | full-time, part-time, contract, internship |
applyUrls | 67% | ATS pages (Greenhouse, Lever, Ashby, Workable…) and careers pages |
stack | 63% | 111 technologies recognised (Python, TypeScript, React, PostgreSQL, Rust, Kubernetes, LLMs…) |
locations | 61% | offices or allowed places, e.g. San Francisco, CA, London, UK |
roleCategories | 55% | backend, frontend, fullstack, mobile, data, ml-ai, devops-sre, security… |
remote | 53.8% true | remote work offered |
seniority | 45% | intern, junior, senior, staff, principal, lead, founding, director… |
salaryMin / salaryMax | 37% | first salary range, as numbers, with salaryCurrency and salaryPeriod |
remoteRegions | 34% | worldwide, americas, latam, us, canada, europe, uk, emea, apac… |
contactEmails | 28.8% | contact emails, de-obfuscated (corporate and role addresses) |
equity | 25% | equity or stock options mentioned |
fundingStage | 16.5% | seed, series a…, bootstrapped, profitable |
visaSponsorship | 8.7% | stated in 8.7%: true (offers sponsorship) 3.5%, false (requires existing work authorization) 5.2% |
timezones | 6.4% | UTC-3, EST, "US time zones"… |
ycBatch | 3.9% | Y Combinator batch, e.g. S26 |
Salary currencies measured: USD 252, EUR 19, GBP 4, CAD 4, PLN 3, AUD 1, CHF 1 (of
284 posts with a currency). When a post lists several bands or currencies, all of them
are in salaries.
Latin America eligibility
latamEligible answers "can someone in Latin America apply?" and latamSignals
says why:
| Value | Meaning | Share (n = 848) |
|---|---|---|
true | LATAM or a Latin American country or city in the location, or remote worldwide / Americas (mention:Brazil, remote:worldwide…) | 7.1% |
false | remote restricted to other regions (remote-restricted:us), or an office outside Latin America | 65.9% |
null | the post does not say | 27.0% |
Company email pattern (optional add-on)
With inferEmailPattern, each company domain gets an emailPattern object:
pattern (e.g. first.last), confidence (0–0.99), evidence (the addresses
it was learned from), alternatives, mxValid, mxHosts, emailProvider and
catchAll. Measured on 480 domains: MX valid 95.6%, Google Workspace 71.7%,
Microsoft 365 12.3%.
Most posts publish a role address (jobs@) rather than a personal one, so a
pattern backed by observed addresses is rare: 4 of 480 domains (0.8%) in the
sample above, 15 of 1,510 over the last 12 months. You are charged only for
those. For every other domain you still get the MX records and provider and a
best guess marked inferred: true, free.
No email is ever sent and no mail server is probed (no SMTP): catchAll is always
null.
One row per company (outputType: companies)
Set Output to companies and every company becomes one row that merges all its
posts in the months and filters you chose. Companies are grouped by domain
(companyKey: "acme.com"); a company whose posts never give a domain is grouped by
its normalized name (companyKey: "name:acme"), and a name-only post joins the
domain group when that name appears with exactly one domain in the range. Filters
apply to the posts before grouping, so remoteOnly gives you companies with
remote posts, built from those posts only. Rows come newest hiring first, and
maxItems counts companies.
What a company row adds: monthsHiring, monthsCount, postCount,
firstPostedAt, lastPostedAt, lastPostUrl, lastHeaderLine, lastPostText,
postIds / postUrls, authors, companyNames, remotePosts,
latamEligiblePosts and locationPolicies, plus the post fields aggregated: roles,
stack, locations, countries, remote regions, remote and latamEligible (true when
any post says so), salary range (lowest and highest bound of the most common
currency and period, never mixing currencies), every salary band with its month,
contact emails, apply links, ATS, funding stage, YC batch and the email pattern.
Measured on 2 Oct 2026 over the last 12 monthly threads (November 2025 to October 2026, n = 1,822 companies from 3,475 posts):
| Field | Filled |
|---|---|
grouped by domain | 84.0% |
company | 95.1% |
roles | 81.5% |
stack | 69.0% |
applyUrls | 64.7% |
remote true | 56.3% |
contactEmails | 38.3% |
atsProviders | 34.6% |
| salary range | 34.2% |
fundingStage | 18.4% |
latamEligible true | 6.1% |
ycBatch | 3.4% |
34.6% of those companies posted more than once in the 12 months, and 18.7% in three months or more (up to 12 posts; 1.91 posts per company on average). The "Who wants to be hired?" thread is not read in this mode: job seekers are not companies.
Privacy
- Corporate and role addresses posted by a company are delivered as published.
- Personal-domain addresses (gmail, outlook, yahoo, proton, icloud…) are removed
from
contactEmailsand hidden inrawTextandrawHtmlunless you enableincludePersonalEmails. In the measured sample, 19 of 269 addresses in company posts were on personal domains. - "Who wants to be hired?" posts are individuals, and so are the "SEEKING WORK"
posts of the Freelancer thread. Both threads are off by default; when you add one,
every email, phone number and CV link of those posts (including links to a CV
document) is hidden unless you also enable
includePersonalEmails. Turn it on only if you have a lawful basis to process that data. - The Hacker News username of the author is delivered, as shown on the site.
Input examples
The latest month, everything (what the daily test runs):
{}
Remote engineering posts of September 2026 with the email pattern:
{"months": ["2026-09"],"roleKeywords": ["engineer"],"remoteOnly": true,"inferEmailPattern": true,"maxItems": 50}
Every company that hired in the last six months, one row each:
{"outputType": "companies","months": ["latest", "latest-1", "latest-2", "latest-3", "latest-4", "latest-5"],"maxItems": 500}
Three months of posts open to Latin America, for a scheduled run:
{"months": ["latest", "latest-1", "latest-2"],"latamOnly": true,"stack": ["TypeScript", "Python"]}
months accepts 2026-10, October 2026, latest and latest-N. All filters are
applied to the parsed rows, so they filter exactly what you see.
Output example
One row, shortened (rawText and rawHtml cut; addresses replaced by examples):
{"rowType": "post","postId": "49613617","postUrl": "https://news.ycombinator.com/item?id=49613617","storyTitle": "Ask HN: Who is hiring? (September 2026)","threadType": "hiring","postIntent": "hiring","month": "2026-09","author": "hn_user","postedAt": "2026-09-01T16:03:11Z","headerLine": "Search Atlas | Product Engineer | REMOTE (anywhere, EST hours) | Full-time contractor | $23-$34 USD/hour | https://careers.searchatlas.com/jobs/599248-pro","company": "Search Atlas","companyUrl": "https://careers.searchatlas.com/jobs/599248-product-engineer-pm","domain": "searchatlas.com","roles": ["Product Engineer (Product Manager role, not a Full-stack role)"],"employmentTypes": ["full-time", "contract"],"stack": ["TypeScript", "Python", "React", "Django", "LLMs"],"remote": true,"locationPolicy": "remote","remoteRegions": ["worldwide"],"latamEligible": true,"latamSignals": ["remote:worldwide"],"timezones": ["EST", "EST hours"],"salaryMin": 23,"salaryMax": 34,"salaryCurrency": "USD","salaryPeriod": "hour","visaSponsorship": null,"contactEmails": ["first.last@example.com"],"contactEmailsDetail": [{ "email": "first.last@example.com", "type": "named", "domain": "example.com", "obfuscated": false }],"personalEmailsHidden": 0,"applyUrls": ["https://careers.searchatlas.com/jobs/599248-product-engineer-pm"],"emailPattern": {"pattern": "first.last","confidence": 0.5,"inferred": false,"evidenceCount": 1,"mxValid": true,"mxHosts": ["aspmx.l.google.com"],"emailProvider": "Google Workspace","catchAll": null,"charged": true},"rawText": "Search Atlas | Product Engineer | REMOTE (anywhere, EST hours) | …","scrapedAt": "2026-10-01T23:40:12.511Z"}
One company row, shortened (lists cut; the address replaced by an example):
{"rowType": "company","companyKey": "albert.com","company": "ALBERT","domain": "albert.com","monthsHiring": ["2026-09", "2026-08", "2026-07", "2026-06"],"monthsCount": 4,"postCount": 4,"firstPostedAt": "2026-06-03T00:08:25Z","lastPostedAt": "2026-09-08T19:19:18Z","lastPostUrl": "https://news.ycombinator.com/item?id=49615435","lastHeaderLine": "ALBERT | REMOTE ALMOST ANYWHERE IN THE WORLD| Hiring principal and distinguished engineers to build net new products | up to ~ $750k","postIds": ["49615435", "49172196", "48751913", "48377948"],"seniority": ["principal"],"stack": ["JavaScript", "Python", "React", "React Native", "PostgreSQL"],"remote": true,"remotePosts": 4,"remoteRegions": ["worldwide"],"latamEligible": true,"latamEligiblePosts": 4,"latamSignals": ["remote:worldwide"],"salaryMin": 750000,"salaryMax": 750000,"salaryCurrency": "USD","salaryPeriod": "year","salaries": [{ "min": null, "max": 750000, "currency": "USD", "period": "year", "raw": "$750k", "month": "2026-09", "postId": "49615435" }],"equity": true,"contactEmails": ["recruiting@example.com"],"fundingStage": "profitable","emailPattern": { "pattern": "first.last", "confidence": 0.1, "inferred": true, "mxValid": true, "emailProvider": "Google Workspace", "catchAll": null, "charged": false },"lastPostText": "ALBERT | REMOTE ALMOST ANYWHERE IN THE WORLD| Hiring principal and distinguished…"}
Pricing
Pay per event:
| Event | Price |
|---|---|
Post (one row, outputType: posts) | $0.004 ($4 per 1,000 posts) |
Hiring company (one row, outputType: companies) | $0.01 ($10 per 1,000 companies) |
| Company email pattern (once per domain per run, only when backed by observed addresses) | $0.01 |
| Actor start | $0.00001 |
Error rows are never charged, and a post or a company is never charged twice in the same run. When your maximum cost per run is reached, the run stops cleanly.
What real runs cost (measured on the Apify platform, 2 Oct 2026, 512 MB)
| Input | Result | Time | You pay |
|---|---|---|---|
{} (latest month, 100 posts) | 100 posts | 5 s | $0.40 |
September 2026, engineer, remote only, email pattern, 50 | 50 posts + 1 email pattern | 6 s | $0.21 |
Latest 3 months, latamOnly, email pattern | 43 posts | 6 s | $0.17 |
outputType: companies (latest month, 100) | 100 companies | 4 s | $1.00 |
outputType: companies, latest 2 months, email pattern, 150 | 150 companies + 3 email patterns | 7 s | $1.53 |
outputType: companies, latest 12 months, 100 | 100 companies (3,483 posts merged) | 55 s | $1.00 |
| Maximum cost per run $0.50, 300 posts asked | 124 posts, then a clean stop | 4 s | $0.50 |
A month in the future (2031-01) | 1 error row explaining why | 1 s | $0.00 |
Set Max items to control the cost: you pay for the rows you get, nothing for the time the run takes.
How it compares (measured on 1 Oct 2026)
We read the output schemas of the 10 Hacker News "Who is hiring" actors in the Apify Store. The richest declares 25 fields. None of them delivers the company domain, salary as numbers, Latin America eligibility, an email pattern or MX records.
FAQ
Where does the data come from? From the public Hacker News search API, the same one the Hacker News search page uses. No login, no cookies, no browser, no API key.
Can I export Hacker News jobs to CSV or Excel? Yes. Every run is an Apify dataset: download it as CSV, JSON, Excel, XML or HTML, or read it through the Apify API. The dataset has ready views (overview, outreach, LATAM, compensation, companies).
Can I run it every month? Yes: schedule the actor (or a saved task) with
months: ["latest"] and send each dataset to Google Sheets, Slack, Zapier or a webhook
with Apify integrations. Each row has postId and postedAt to keep only the new ones.
How fast is it? On the Apify platform (2 Oct 2026, 512 MB): 100 posts in 5 seconds, 300 posts from two months in 6 seconds, and 12 months merged into companies in 55 seconds, with a memory peak of 102 MB. In local tests: 9,040 posts (12 months of both threads) in 42 seconds. Companies: 1,822 companies from 12 months in 23 seconds; the whole archive (184 threads, 90,427 posts, 24,169 companies) in 3 min 19 s within 512 MB of memory (measured on 2 Oct 2026).
Posts or companies? Posts when you want every job ad (one company can post every month). Companies when you want a deduplicated list of who is hiring, with how often and for what.
Which months exist? Monthly hiring threads exist from April 2011. The "Freelancer? Seeking freelancer?" thread was last posted in October 2025, so recent months have none; the run tells you when a requested thread does not exist.
The current month has few posts. The thread opens on the first weekday of the month and grows for days: on 1 Oct 2026 it had about 100 posts, while September 2026 ended with 254.
Why is a field empty? Posts are free text and many do not state a salary, a
stack or a location. Every field is always present, with null when the post does
not say.
Does it send emails or verify mailboxes? No. It only reads published posts and checks MX records by DNS.
Can I get the replies? Rows are top-level posts (the job posts). replyCount
says how many direct replies each one has, and replyIds lists their Hacker News IDs.