How to Scrape Company Career Pages and Check Hiring Coverage
A company with no returned jobs may have no matching vacancies, or the scraper may have failed to find its hiring system. Those outcomes must stay separate if you are building a hiring tracker.
The Company Career Page Scraper attempts to discover career pages from company homepages and collect jobs through supported applicant tracking systems, or ATSs. I maintain this Apify Actor. It also accepts direct board URLs and can extract structured information from descriptions with AI. It cannot guarantee coverage of every company website.

Establish coverage before narrowing the jobs
Start with one company, a positive job cap, and AI enrichment disabled. This checks source discovery and raw fields before you spend time interpreting extracted skills or salaries.
The documented adapters cover Greenhouse, Lever, Ashby, Workday, Oracle HCM, SmartRecruiters, Workable, and Radancy. Discovery tries homepage links, likely career paths, sitemaps, board-token matching, and a Workable index lookup. A supported ATS does not mean every tenant or company homepage will resolve successfully.
Open the Actor on Apify, choose Input, switch to JSON, and enter:
{
"startUrls": [
{"url": "https://www.figma.com"}
],
"maxJobsPerCompany": 20,
"enrichWithAI": false
}
Click Start. The cap is twenty jobs per company, not per run. With five companies, the same setting permits up to 100 job records. The default is 200 per company and the minimum is one.
When the run finishes, inspect both the dataset and the key-value store. Open its RUN_SUMMARY record. The README documents requested, resolved, and missed company counts, adapters used, jobs filtered out, and discovery routes tried for unresolved companies.
Do not turn an unresolved company into a zero-vacancy row. Try its verified direct ATS board URL in a small separate run if the board is supported. Review the returned companyName, companyDomain, and careersUrl even after successful discovery. The README specifically notes weaker evidence for an Ashby board matched only by a guessed token because that source lacks a published company name for the check.
Inspect the job identity and source fields
The output includes jobId, title, companyDomain, companyName, source, careersUrl, jobUrl, and applyUrl. Retain these before selecting more convenient analysis columns. They let you return from a normalized row to the employer's original vacancy.
Other fields include department, team, location, locationCity, locationRegion, locationCountry, remote, employmentType, postedAt, updatedAt, and scrapedAt. Availability varies by source. A collection timestamp is not the posting date, and a missing posting date should not be replaced by the day you first saw the role.
The historical output documentation illustrates remote: "unknown" even for a record with a location and employment type. Preserve that distinction. A city in the location field does not establish whether the role is on-site, hybrid, or remote.

Add filters without losing the unknowns
Once the company resolves, use keywords for terms found in the title, department, or team. Multiple keywords are alternatives: a match to any of them qualifies. location is a text filter, not a geographic radius.
You can also filter workplaceType to remote, hybrid, or on-site, add employmentType, or set postedAfter to an ISO date. Filters combine with AND, but the documentation keeps jobs whose ATS does not publish the relevant workplace, employment, or posting-date field.
For a remote engineering tracker, add the engineering keyword and remote filter, then divide the output into confirmed remote and unknown rows. Do not label every retained row remote. For a “posted this week” view, separate jobs with verified qualifying dates from undated ones that passed through the filter.
This approach avoids discarding potentially relevant vacancies while still keeping your published counts honest. Include the number of unknowns beside the number of confirmed matches.
Use AI enrichment as a review aid
enrichWithAI defaults to true. Enabling it asks the Actor to extract skills, requirements, responsibilities, benefits, and salary information from descriptions. It can make a reading queue easier to search, but extraction is not an employer-verified structured record.
Keep descriptionText and descriptionHtml with the enriched fields. Before using a skill count in a report, check several matches against the description, distinguishing a required skill from a preferred one or a technology mentioned only as background. A blank skill array does not prove that a role requires no skills.
For compensation, verify salaryMin, salaryMax, salaryCurrency, and salaryPeriod together. Do not combine annual and hourly ranges or currencies in one average. Check whether a range applies to the location under study and whether the description states base salary or another compensation measure. Unclear values belong in a review queue.
Build a hiring change sheet
Export JSON when retaining arrays and full descriptions; use CSV for a selected job table. Keep a company-coverage sheet from RUN_SUMMARY alongside the vacancy export. That sheet should distinguish resolved sources, unresolved sources, and sources with no matching records.
For later runs, join jobs by companyDomain and jobId, keeping source URLs for fallback review. Label newly observed jobs as first seen in your collection, which is different from newly posted. A missing vacancy may reflect the cap, filters, discovery failure, or a removed listing. Confirm it on the employer's board before marking it closed.
The company career-page Node.js example supports repeat collection. If you also use LinkedIn jobs or Dice listings, keep their observations separate until you can match the actual vacancy. Clutch profiles are a separate company-research source.
Budget by account tier
Result-event rates as of September 6, 2026 are $0.003 on FREE, $0.0025 on BRONZE, $0.002 on SILVER, and $0.0012 on GOLD, PLATINUM, or DIAMOND. Twenty results on FREE cost $0.06 in result events. The start event is $0.00005 per GB of allocated memory, minimum one event.
New rates are scheduled for September 9, so review live pricing before scheduling. The active event table does not list a distinct AI-enrichment event; check actual run charges and any separately billed usage rather than adding the README's illustrative AI-processing estimate to the price automatically. Unresolved companies do not produce job-result fees, but the run can still incur its start charge.
Frequently asked questions
Does the scraper work with every company website?
No. It attempts career-page discovery and supported ATS extraction, but some companies remain unresolved. Inspect the log and RUN_SUMMARY, then try a verified direct board URL where supported.
Why can a remote-filtered result have unknown remote status?
The documented filters retain jobs when the ATS does not publish the filtered field. Separate confirmed remote roles from unknowns in your analysis.
Are AI-enriched skills and salary fields guaranteed correct?
No. They are extracted interpretations of the description and can be incomplete or wrong. Verify important values against descriptionText and the original job page.
