Indeed Jobs Scraper With Employer Email Leads avatar

Indeed Jobs Scraper With Employer Email Leads

Pricing

from $2.99 / 1,000 results

Go to Apify Store
Indeed Jobs Scraper With Employer Email Leads

Indeed Jobs Scraper With Employer Email Leads

Indeed Jobs Scraper with Employer Email Leads extracts job listings, company details, job titles, locations, salaries, descriptions, and publicly available employer contact emails. Build targeted hiring-company lead lists for recruitment, sales, and business development.

Pricing

from $2.99 / 1,000 results

Rating

0.0

(0)

Developer

SimpleAPI

SimpleAPI

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

0

Monthly active users

3 days ago

Last modified

Share

Indeed Jobs Scraper — Employer Leads, Emails and Phone Numbers

This Actor scrapes Indeed job listings and turns each hiring employer into a single lead row — company name, job title, salary, location, the employer's own website, its Facebook/X/Instagram profile as recorded by Indeed, and any public email or phone address found on that company's own site. It's built for recruiters, B2B sales teams and staffing agencies that prospect from hiring signals instead of static company lists. Contact hit rates are measured and reported honestly every run, not promised.


What is Indeed Jobs Scraper With Employer Email Leads?

It's an Apify Actor that queries Indeed's mobile-app GraphQL endpoint (apis.indeed.com/graphql — the same one Indeed's iOS app calls) for job listings, then optionally crawls the employer's own website to find a public email and phone number. No Playwright and no HTML parsing on the Indeed side — just authenticated GraphQL requests. No Indeed account, login, or API key is required to run it; the Actor authenticates with a public, non-secret iOS-app key.

Key features:

  • 🔎 Two ways to find employers — search by keyword, location, radius and country (63 Indeed domains supported), or paste Indeed search / /cmp/ company page URLs directly
  • 🏢 One row per employer, not per duplicate listinguniqueCompaniesOnly collapses repeat postings from the same company into a single row carrying listingsForThisEmployer and the employer's other open roles
  • 📧 Employer contact lookup — visits the employer's own site (homepage plus up to 9 more best-scoring contact/about/imprint pages) and extracts public mailto: addresses and tel: numbers, filtered against a denylist of tracker/ATS/placeholder domains and validated with real phone-numbering-plan logic
  • 🔗 Social profiles from two sources — Facebook/X/Instagram read straight out of Indeed's own employer record (no extra request), plus LinkedIn/Twitter/Facebook/Instagram/YouTube found during the website crawl
  • 🎚️ Real filters — freshness (last 24 hours to 30 days), job type, remote/hybrid, US seniority level, and sort by relevance or date
  • 📤 Structured JSON output via the Apify dataset, exportable to CSV, Excel, JSON, JSONL, XML or an RSS feed

What data can I extract with Indeed Jobs Scraper?

Every field below is written by the Actor's row-builder (_transform_to_required_structure plus _build_output_row in src/main.py), not just the 13 columns shown in the default dataset table view.

Lead fields (flat, always present on every row)

FieldExample ValueUse Case
jobId"a1b2c3d4e5f6g7h8"Unique Indeed job key, dedup key
title"Sales Representative"Role that triggered the lead
companyName"Acme Retail Group"Employer name
locationShort"New York, NY"Quick geo filter
postedText"3 days ago"Recency at scrape time
salaryText"$55,000 - $70,000 a year"Compensation signal
jobUrl"https://www.indeed.com/viewjob?jk=a1b2c3d4e5f6g7h8"Link back to the listing
employerName"Acme Retail Group"CRM company field
employerWebsite"https://acmeretailgroup.com"Outbound target / enrichment key
employerEmail"careers@acmeretailgroup.com"Best public email found
employerPhone"+12125551234"Best public phone found, E.164
employerContactStatus"ok"Why the lookup succeeded/failed
hasEmployerEmailtrueQuick filter flag
hasEmployerPhonefalseQuick filter flag
hasEmployerContacttrueEmail or phone present
listingsForThisEmployer3Open-role count behind this row
isEmployerRolluptrueWhether this row is a rollup or a single listing

employer.* — employer identity, from Indeed's own record

FieldExample ValueUse Case
employer.key"c9d8e7f6"Indeed's internal employer ID (used to group listings)
employer.name"Acme Retail Group"
employer.identityUsed"employerKey"Which identity strategy grouped this employer (employerKey, employerName, or jobKey)
employer.websiteUrl"acmeretailgroup.com"Raw value as Indeed lists it, before normalization
employer.indeedCompanyPageUrl"https://www.indeed.com/cmp/Acme-Retail-Group"Indeed's own employer profile page
employer.industry"Retail"
employer.numEmployees"501 to 1,000 employees"Company-size band
employer.revenue"$100M to $500M (USD)"
employer.socialProfiles.facebook/twitter/instagram"https://facebook.com/acmeretail"From Indeed's dossier, no extra request
employer.socialProfilesSource"indeed_employer_dossier"null when Indeed had none on file

employerContacts.* — the website contact lookup result

FieldExample ValueUse Case
employerContacts.websiteUrl"https://acmeretailgroup.com"Normalized site that was crawled
employerContacts.status"ok"ok, blocked, js_required, unreachable:*, no_website_on_indeed, lookup_disabled
employerContacts.emails[]["careers@acmeretailgroup.com"]All emails surviving the junk filter
employerContacts.emailsOnCompanyDomain[]["careers@acmeretailgroup.com"]Emails on the employer's own registrable domain
employerContacts.primaryEmail"careers@acmeretailgroup.com"Best single email (on-domain preferred) — same value as employerEmail
employerContacts.emailsDroppedAsJunk2Addresses rejected as trackers/placeholders
employerContacts.phones[]["+12125551234"]Validated (libphonenumber) numbers
employerContacts.phonesUncertain[][]Numbers found but not validated as real
employerContacts.primaryPhone"+12125551234"Best single phone — same value as employerPhone
employerContacts.socialProfiles.linkedin/twitter/facebook/instagram/youtube[]["https://linkedin.com/company/acme-retail"]Profiles found on the crawled pages
employerContacts.sourceUrl"https://acmeretailgroup.com"First page any contact was found on
employerContacts.emailSourceUrl / .phoneSourceUrl"https://acmeretailgroup.com/contact"Provenance per contact type
employerContacts.contactPageUrl"https://acmeretailgroup.com/contact"Highest-scoring contact page checked
employerContacts.pagesChecked[] / .pagesCheckedCount2Audit trail of what was actually fetched
employerContacts.hasEmail / .hasPhone / .hasAnyContacttrueBoolean summary flags

otherListingsForThisEmployer[] — up to 25 of the employer's other open roles when uniqueCompaniesOnly is on: jobId, title, locationShort, postedText, salaryText, jobUrl.

job.* — the underlying Indeed listing (unchanged from a plain job scraper)

FieldExample ValueUse Case
job.descriptionText / job.descriptionHtml"We are seeking a…"Full posting text
job.isRemote / job.remoteLocationfalseRemote flag
job.jobType[]["Full-time"]From Indeed's attribute keys
job.attributes[]["401(k)", "Health insurance"]Raw Indeed attribute labels
job.benefits[]["Health insurance", "Paid time off"]Keyword-matched subset of attributes
job.salary.min/max/type/currency/weeklyMin/weeklyMax55000 / 70000 / "yearly"Parsed compensation
job.dates.postedText/datePublished/pubDateEpoch"2026-08-13"Freshness fields
job.hiring.*, job.status.expired/newJobfalseSee note below — always false/null, not live-derived on this endpoint

company.* — Indeed's employer profile fields: name, industry, revenue, numEmployees, description, addresses[], rating.score/rating.count (always null — Indeed's mobile endpoint returns no rating on this query), ceo.name/ceo.photoUrl, branding.logoUrl/branding.headerUrl, links.corporateWebsite/.facebook/.instagram/.twitter/.indeedCompanyPage, emails[] (mirrors employerContacts.emails).

location.*: countryCode, country, state, stateName, city, postalCode, streetAddress, formattedShort, formattedLong, latitude/longitude (always null — not requested from the GraphQL API on this query).

apply.*: jobUrl, applyUrl, originalApplyUrl, thirdPartyApplyUrl, indeedApplyEnabled.

sourceMeta.* (source, scrapingInfo.page/.index) and _raw (the complete unshaped record, kept for debugging/advanced use).

Note on placeholder fields: job.status.expired, job.status.newJob, job.hiring.urgentlyHiring, job.hiring.highVolumeHiring, job.hiring.isRepost, job.hiring.organicApplyStarts/.numOfCandidates, company.rating.*, company.foundedYear, and location.latitude/longitude are always false/null in the current output — Indeed's mobile GraphQL endpoint does not return live values for these on the query this Actor sends. They're kept in the schema for compatibility with a plain job-listing scraper's output shape, not because they carry live data.

📧 Employer contact & social data

employerContacts is the section that turns a job posting into a sales lead: primaryEmail/primaryPhone for outreach, emailsOnCompanyDomain to separate a real company mailbox from a third-party form-vendor address, and status + pagesChecked so a "no contact found" row is distinguishable from a lookup that never ran. A typical use: filter rows to hasAnyContact: true and push employerName, employerEmail, employerPhone straight into a CRM import.

🎯 Targeting and segmentation fields

location.city/.state/.postalCode narrow a lead list to a territory; job.dates.datePublished and fromDays isolate employers hiring right now versus weeks ago; employer.industry, employer.numEmployees and employer.revenue let you segment a lead list by company size or vertical before you ever open a CRM.


Why not build this yourself?

Building an "Indeed jobs plus employer contact leads" pipeline from scratch means solving several separate scraping problems before the first usable lead row exists.

  • Indeed has no documented public search API for this — job data comes back from its mobile-app GraphQL endpoint, authenticated with the same indeed-api-key/user-agent pair Indeed's own iOS app uses (reverse-engineered and published by the open-source JobSpy project). That key is a single point of failure: if Indeed rotates it, every integration built on it starts returning 401/403 at the same moment, and there's no vendor support line to call.
  • Indeed shows the same employer under many separate listings. Collapsing those into one row per employer — with the employer's other open roles attached, and billed exactly once — is bookkeeping most scrapers don't do.
  • Indeed's own data never includes an employer email or phone number. Getting one means a second, independent scrape of the employer's own website, with its own blocking behavior: Cloudflare-protected surfaces here were measured to key off TLS fingerprint rather than IP, so common Chrome/Edge client fingerprints returned a 28 KB challenge page in testing, while a specific pool of Safari/Firefox fingerprints did not.
  • Separating a real employer contact from junk needs an actively maintained denylist, not a single regex — a naive mailto: sweep on live sites returns error-tracker DSNs, Wix/Squarespace plumbing addresses, ATS-vendor mailboxes (icims.com, greenhouse.io, workday.com…), and image filenames like logo@2x.png that happen to match an email pattern.

If you already have engineering time to reverse-engineer and maintain a mobile-API integration, build a Cloudflare-resistant crawler, and keep a junk-email filter current, doing this yourself is possible. For everyone else, this Actor runs that pipeline without the ongoing maintenance.


How to use data extracted from Indeed?

💼 B2B sales and SDR teams

Set hiringSearchTerm to a role that signals budget or growth (e.g. a specific skill or seniority you sell into), narrow with location/radius and fromDays to the freshest signal, then filter the resulting rows to hasEmployerContact: true. employerName, employerEmail, employerPhone and employer.industry map straight into an outreach list — listingsForThisEmployer doubles as a quick "how urgently are they hiring" score.

🧑‍💼 Staffing and recruitment agencies

Run the same search on a schedule against a client's target industry or geography, and diff successive runs on jobId/employer.key to see which employers are hiring consistently versus a one-off posting. job.dates.datePublished and postedText give a freshness read without opening Indeed manually.

📊 Market research and labour intelligence

Aggregate employer.industry, employer.numEmployees, location.city/.state and job.salary.min/.max across a run to map hiring density and pay bands by vertical or metro — for example, comparing median job.salary.min across location.city values for the same hiringSearchTerm.

🤖 AI agents and automated pipelines

Wrap the Actor as a tool that answers "who is hiring for X near Y right now, and how do I reach them" mid-conversation, or feed employerContacts and job fields into an enrichment pipeline that appends firmographic or intent data before a lead reaches a rep.


🔼 Input sample

Fill in Option 1 (search terms) or Option 2 (urls) — Option 2 wins if both are filled. No input parameter is required; every field has a working default.

ParameterRequiredTypeDescriptionExample Value
hiringSearchTermNostringWhat the employer is hiring for — job title, skill or keyword. Default "Sales"."Warehouse Associate"
locationNostringRestrict the employer list to one hiring area. Leave empty for the whole country. Default ""."Chicago, IL"
radiusNostring (enum)Widen or tighten the hiring area. Values: "", "0", "5", "10", "15", "25", "35", "50", "100". Default ""."25"
countryCodeNostring (enum)Which Indeed domain to search (63 country codes, e.g. us, uk, ca, de). Default "us"."ca"
maxLeadRowsNointegerNumber of distinct employers wanted (rollup ON) or listings wanted (rollup OFF). Min 1, max 10000. Default 10.50
uniqueCompaniesOnlyNobooleanON: one row per employer, charged once. OFF: one row per listing. Default true.true
findEmployerContactsNobooleanVisit the employer's own site for public contact details. Default true.true
maxContactPagesPerCompanyNointegerPages checked per employer site (homepage + best-scoring pages). Min 1, max 10. Default 3.3
onlyEmployersWithContactNobooleanKeep only employer rows where a contact was found. Default false.false
contactRequestTimeoutSecondsNointegerTimeout per employer-website request, in seconds. Min 5, max 60. Default 20.20
defaultPhoneRegionNostringTwo-letter country code for numbers written without a +prefix. Default "" (inferred from the site's domain)."US"
fromDaysNostring (enum)Freshness of the hiring signal. Values: "0" (no filter), "1", "3", "7", "14", "30". Default "0"."7"
jobTypeNostring (enum)Values: "", fulltime, parttime, contract, temporary, internship, volunteer, permanent, seasonal, freelance. Default ""."fulltime"
remoteNostring (enum)Values: "", remote, hybrid. Default "".""
levelNostring (enum)US only. Values: "", entry_level, mid_level, senior_level. Default "".""
sortNostring (enum)Values: "", relevance, date. Default "relevance"."date"
urlsNoarray of stringIndeed search or /cmp/ employer URLs. Runs instead of Option 1 when filled.["https://www.indeed.com/jobs?q=sales&l=New+York%2C+NY"]
maxRowsPerUrlNointegerPer-URL row cap when more than one URL is pasted (ignored with a single URL). Min 1, max 1000.20
enableUniqueJobsNobooleanDeduplicate listings across pages/URLs before rolling up employers. Default true.true
includeSimilarJobsNobooleanNo-op on this endpoint — kept so older saved inputs still load. Default true.true
queryNostringCompatibility field — overrides hiringSearchTerm when filled.(leave empty)
maxRowsNointegerCompatibility field — overrides maxLeadRows when filled. Min 1, max 10000.(leave empty)
proxyConfigurationNoobjectApify proxy config. No proxy is used by default; the Actor falls back to datacenter, then residential, on a block.{"useApifyProxy": false}
{
"hiringSearchTerm": "Sales",
"location": "New York, NY",
"radius": "25",
"countryCode": "us",
"maxLeadRows": 25,
"uniqueCompaniesOnly": true,
"findEmployerContacts": true,
"maxContactPagesPerCompany": 3,
"onlyEmployersWithContact": false,
"contactRequestTimeoutSeconds": 20,
"fromDays": "7",
"jobType": "fulltime",
"sort": "date"
}

Common pitfall: query and maxRows are compatibility fields kept for saved inputs from a plain job-listing scraper. If either is filled in — even accidentally left over from a copied input — it silently overrides hiringSearchTerm or maxLeadRows respectively. Leave both empty unless you're intentionally re-running an old saved input.


🔽 Output sample

Each run writes one JSON record per employer (or per listing, with rollup off) to the Apify dataset — typed, consistently shaped, and exportable as JSON, JSONL, CSV, Excel, XML or RSS. Runs that find no search input or get blocked by Indeed on every proxy tier write a single unbilled accounting record (_type: "run_accounting") instead of a lead row.

{
"jobId": "a1b2c3d4e5f6g7h8",
"title": "Sales Representative",
"companyName": "Acme Retail Group",
"locationShort": "New York, NY",
"postedText": "3 days ago",
"salaryText": "$55,000 - $70,000 a year",
"jobUrl": "https://www.indeed.com/viewjob?jk=a1b2c3d4e5f6g7h8",
"employerName": "Acme Retail Group",
"employerWebsite": "https://acmeretailgroup.com",
"employerEmail": "careers@acmeretailgroup.com",
"employerPhone": "+12125551234",
"employerContactStatus": "ok",
"hasEmployerEmail": true,
"hasEmployerPhone": true,
"hasEmployerContact": true,
"listingsForThisEmployer": 3,
"isEmployerRollup": true,
"employer": {
"key": "c9d8e7f6",
"name": "Acme Retail Group",
"identityUsed": "employerKey",
"websiteUrl": "acmeretailgroup.com",
"indeedCompanyPageUrl": "https://www.indeed.com/cmp/Acme-Retail-Group",
"industry": "Retail",
"numEmployees": "501 to 1,000 employees",
"revenue": "$100M to $500M (USD)",
"socialProfiles": {
"facebook": "https://facebook.com/acmeretail",
"twitter": "https://x.com/acmeretail",
"instagram": null
},
"socialProfilesSource": "indeed_employer_dossier"
},
"employerContacts": {
"websiteUrl": "https://acmeretailgroup.com",
"status": "ok",
"emails": ["careers@acmeretailgroup.com"],
"emailsOnCompanyDomain": ["careers@acmeretailgroup.com"],
"primaryEmail": "careers@acmeretailgroup.com",
"emailsDroppedAsJunk": 2,
"phones": ["+12125551234"],
"phonesUncertain": [],
"primaryPhone": "+12125551234",
"socialProfiles": {
"linkedin": ["https://linkedin.com/company/acme-retail"],
"twitter": [],
"facebook": [],
"instagram": [],
"youtube": []
},
"sourceUrl": "https://acmeretailgroup.com",
"emailSourceUrl": "https://acmeretailgroup.com/contact",
"phoneSourceUrl": "https://acmeretailgroup.com/contact",
"contactPageUrl": "https://acmeretailgroup.com/contact",
"pagesChecked": ["https://acmeretailgroup.com", "https://acmeretailgroup.com/contact"],
"pagesCheckedCount": 2,
"hasEmail": true,
"hasPhone": true,
"hasAnyContact": true
},
"otherListingsForThisEmployer": [
{
"jobId": "z9y8x7w6",
"title": "Store Manager",
"locationShort": "Brooklyn, NY",
"postedText": "1 week ago",
"salaryText": "$65,000 a year",
"jobUrl": "https://www.indeed.com/viewjob?jk=z9y8x7w6"
}
],
"job": {
"id": "a1b2c3d4e5f6g7h8",
"title": "Sales Representative",
"descriptionText": "We are seeking a motivated Sales Representative...",
"isRemote": false,
"jobType": ["Full-time"],
"attributes": ["401(k)", "Health insurance", "Paid time off"],
"benefits": ["Health insurance", "Paid time off"],
"salary": {
"text": "$55,000 - $70,000 a year",
"currency": "USD",
"type": "yearly",
"min": 55000,
"max": 70000
},
"dates": {
"postedText": "3 days ago",
"datePublished": "2026-08-13"
},
"status": { "expired": false, "newJob": false }
},
"company": {
"name": "Acme Retail Group",
"industry": "Retail",
"numEmployees": "501 to 1,000 employees",
"emails": ["careers@acmeretailgroup.com"]
},
"location": {
"countryCode": "US",
"country": "United States",
"state": "NY",
"stateName": "New York",
"city": "New York",
"formattedShort": "New York, NY"
}
}

How do you filter and target specific employer leads?

Precision targeting here works on three axes. Discovery: hiringSearchTerm + location/radius searches Indeed the way a recruiter would; urls lets you paste an exact Indeed search or /cmp/ employer page instead — URL query parameters (q, l, radius, fromage, jt, sort) override the top-level settings for that URL only, which matters when you're running several saved Indeed searches at once. Scope precision: location + radius narrow the hiring area; countryCode picks the Indeed domain (and therefore the country the employer list is drawn from); fromDays isolates employers hiring in a recent window — note this is mutually exclusive with jobType/remote server-side, so when fromDays is set those two become client-side post-filters instead. Volume and quality: maxLeadRows sets how many distinct employers (or listings) you want; onlyEmployersWithContact trims the list to rows with a verified public email or phone, at the cost of removing roughly 7 of every 10 rows at the measured hit rate; uniqueCompaniesOnly is the switch between an employer-level lead list and a raw listing feed.

Three real input examples:

{ "hiringSearchTerm": "warehouse", "location": "Dallas, TX", "radius": "25", "fromDays": "3", "maxLeadRows": 100 }
{ "hiringSearchTerm": "software engineer", "jobType": "fulltime", "remote": "remote", "level": "senior_level", "maxLeadRows": 40 }
{ "urls": ["https://www.indeed.com/jobs?q=nurse&l=Austin%2C+TX&radius=15&sort=date"], "onlyEmployersWithContact": true, "maxLeadRows": 30 }

▶️ Want to try other scrapers?

There's no second Indeed scraper on this account today — this Actor is the account's only Indeed integration. If your lead-generation workflow spans other directories, these SimpleAPI scrapers cover comparable ground:

ScraperWhat it extracts
Google Maps Reviews Scraper (Bad Review Finder)Local business listings and their negative-review signal, for outreach targeting
Amazon DE Sellers Leads ScraperMarketplace seller leads with product price and rating data
Shopify Merchant Scraper (Niche and Keyword Store Search)Independent Shopify store leads by niche/keyword
Alibaba Listings Scraper and Supplier ProfilesVerified-supplier leads with MOQ and product data

How to extract Indeed data programmatically

Every run is a standard Apify Actor call: one API request with your APIFY_API_TOKEN, a JSON input body, and a dataset of structured JSON rows back.

🐍 Python example

from apify_client import ApifyClient
client = ApifyClient("<APIFY_API_TOKEN>")
run = client.actor("<username>/indeed-jobs-scraper-with-employer-email-leads").call(
run_input={
"hiringSearchTerm": "sales",
"location": "New York, NY",
"maxLeadRows": 50,
"onlyEmployersWithContact": True,
}
)
for row in client.dataset(run["defaultDatasetId"]).iterate_items():
print(row["employerName"], row["employerEmail"], row["employerPhone"])

🔌 MCP for AI agents

This Actor is reachable through Apify's hosted Actors MCP Server at https://mcp.apify.com (checked 2026-08-16), which exposes any Apify Actor — including this one — as a callable tool over OAuth or a bearer APIFY_API_TOKEN, for MCP clients such as Claude.ai, Claude Code and VS Code. An agent can call it with a hiringSearchTerm and location to pull live employer contact leads mid-conversation, without a separate integration.

📊 Export to spreadsheets or CRM

Export the dataset as CSV or Excel directly from the Apify Console or API, mapping employerName → a company column, employerEmail/employerPhone → contact columns, title/salaryText/postedText → opportunity-context columns, and jobUrl/employer.indeedCompanyPageUrl → source-link columns.


Scraping publicly visible job listings is generally legal — this Actor reads listing and employer data Indeed already serves to any visitor, the same way a browser would, and job postings, salaries and company profiles are business data, not personal data. Indeed's own terms of service should still be checked before large-scale or commercial use.

The employer contact data is a different case: most captured addresses are role-based business mailboxes (careers@, sales@, info@), but a contact page or "our team" page can expose a named individual's email or phone. Where a captured address is tied to an identifiable person rather than a generic company mailbox, GDPR (EU/UK) and CCPA (California) obligations around lawful basis, storage and deletion apply to that record just as they would to any other personal data you collect. Consult legal counsel for commercial applications involving bulk storage of personal data.


❓ FAQ

Does the Actor flag expired or removed job listings?

Not reliably — job.status.expired and job.status.newJob are always false on the current output, because Indeed's mobile GraphQL endpoint doesn't return a live status for these on the fields this Actor requests. Use job.dates.datePublished/postedText to judge freshness instead, and re-run the search periodically — a listing that has actually been pulled from Indeed simply won't reappear in a fresh crawl.

Can I get salary ranges and social profiles along with the contact leads?

Yes. job.salary (text, min, max, currency, type) comes from Indeed's own compensation block on every listing. employer.socialProfiles (Facebook/X/Instagram) comes from the same GraphQL request, at no extra cost. employerContacts.socialProfiles (LinkedIn/Twitter/Facebook/Instagram/YouTube) comes from the employer-website crawl and is only populated when findEmployerContacts finds a matching link on a checked page.

How accurate is the employer contact data?

It's exactly what's publicly published on the employer's own site at the time of the run — nothing is guessed or pattern-generated (no first.last@company.com inference). On this platform, a measured 24-employer sample (Sales / New York, NY / 25 mi) returned a public email or phone for 33% of employers (25% email, 8% phone); across every contact-enabled run measured, the aggregate is 24 of 82 employers (29%), and one nationwide default-input run returned 0 of 10. The rate swings hard by query and location — treat 25–33% as a good result and 0% as a real possibility. Recommend running standard email verification before any bulk outreach.

How many rows can I get per run?

maxLeadRows accepts 1 to 10000 (default 10). With uniqueCompaniesOnly on, the Actor pages through up to 6× the requested row count (minimum 100 listings) looking for that many distinct employers before stopping, so a very high maxLeadRows on a narrow query can return fewer employers than requested once Indeed's own result set is exhausted. maxRowsPerUrl (1–1000) caps rows per individual URL when more than one URL is pasted; with a single URL it's ignored.

What's the difference between "One row per employer" on and off?

ON (uniqueCompaniesOnly: true, the default): every hiring employer appears exactly once and is charged once, with listingsForThisEmployer and its other open roles attached. OFF: one row per job listing, exactly like a plain job scraper, charged per listing. Measured on this platform across two runs, 150 live listings collapsed to 104 and 97 distinct employers (−31% and −35%), with the busiest single employer holding 12 of those listings.

What's the difference between searching by keyword and pasting Indeed URLs?

hiringSearchTerm + location/radius/filters (Option 1) builds the search for you. urls (Option 2) runs instead of Option 1 when filled, and each URL is its own search — Indeed URL parameters (q, l, radius, fromage, jt, sort) override the top-level input for that specific URL. Use Option 2 when you already have exact saved Indeed searches or specific /cmp/ employer pages to work from.

Does this Actor work with Claude, ChatGPT, and AI agent frameworks?

Yes, via Apify's Actors MCP Server (https://mcp.apify.com), which exposes this Actor as a callable tool to MCP clients including Claude.ai, Claude Code, and VS Code. It's also callable as a plain HTTP endpoint by any agent framework using the Apify API.

How does this Actor compare to a typical Indeed job scraper?

A plain Indeed scraper returns one row per listing with no employer enrichment — this Actor adds employer rollup (uniqueCompaniesOnly), Indeed's own social-profile data, and an independent website crawl for public email/phone, while still emitting every field a plain job-listing scraper would (the base job/company/location/apply structure is unchanged and additive).

Can I use this Actor without an Indeed account or API key?

Yes. No Indeed login, cookie, or API key is required — the Actor authenticates against Indeed's mobile-app GraphQL endpoint with a public, non-secret key. You only need an Apify account to run the Actor itself.

What happens if Indeed blocks the request or rotates its API key?

On a 401/403/429 from Indeed, the Actor automatically escalates its proxy tier (direct → datacenter → residential, 3 retries per tier) and retries. If Indeed rotates the underlying mobile-app API key itself, every request will return a hard 401/403 that the proxy ladder cannot fix — this is a real limitation of building on a reverse-engineered endpoint rather than a documented API. Employer-website lookups escalate through the same tiered fallback independently when a specific site blocks the crawl.


Conclusion

Indeed Jobs Scraper With Employer Email Leads turns Indeed's hiring activity into an employer lead list — one row per company, not per duplicate posting — with the salary, location and role data a plain job scraper gives you, plus a real, measured public email and phone lookup on top. It's built for sales teams, recruiters and researchers who need contactable hiring employers, not just job postings, and it reports its own contact-hit rate every run instead of promising one. Start it from the Apify Console or API with a hiring search term and location, or paste Indeed URLs directly, to get your first batch of employer leads.