B2B SaaS Account Qualifier for AI Agents
Pricing
from $10.00 / 1,000 valid leads
B2B SaaS Account Qualifier for AI Agents
Qualify B2B SaaS account URLs into AI-ready lead records with hiring demand, source evidence, compact rows, and next-action routing.
Pricing
from $10.00 / 1,000 valid leads
Rating
0.0
(0)
Developer
DeepAPI
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
0
Monthly active users
4 days ago
Last modified
Categories
Share
Turn B2B SaaS company URLs into AI-ready account qualification records with hiring demand, source evidence, compact lead rows, confidence scores, and next-action routing.
This Actor is built for workflows where an AI agent, sales operator, recruiter, or analyst already has a target account list and needs a fast, source-backed answer:
Should we act on this account now, why, and what should happen next?
What It Does
- Accepts company URLs or bare domains, skips invalid entries, and reports batch input diagnostics in the Actor output.
- Crawls each accepted company website, including likely signal pages such as homepage, careers, jobs, about, and contact pages.
- Follows career subpages, localized jobs paths, and branded external careers sites such as
lifeat{brand}when they are reached from the company's own careers URL. - Follows supported public job-board links from company pages, including Greenhouse, Lever, Ashby, Workable, SmartRecruiters, Teamtailor, Breezy, and Workday.
- Uses provider-specific parsing for Ashby, Lever, and Greenhouse job boards when structured posting data is available.
- Reads embedded Ashby job records from company careers pages when roles are shipped inside script payloads.
- Extracts company-level lead signals:
- hiring or growth language,
- matched role keywords,
- public company emails,
- public LinkedIn company URLs,
- matched public job titles and posting URLs,
- optional country matches.
- Deduplicates results by company domain.
- Merges evidence from company pages and linked job boards into one company-level lead.
- Returns detailed dataset rows, compact lead rows, and run-level recommendations designed for AI agent chaining.
Why It Is Useful
Most lead tools return raw company or contact data. This Actor qualifies accounts by answering whether there is current public hiring demand worth acting on, then returns evidence an agent or operator can audit.
For an AI agent inside Claude, Cowork, or another workflow runner, this means the agent can:
- take a target account list,
- qualify each company,
- inspect structured evidence,
- decide whether to enrich, monitor, recruit, or start outreach,
- pass the record into another Actor or CRM workflow.
No LLM is required for the MVP. The current version uses deterministic extraction and scoring so results are cheaper, repeatable, and easier to audit. LLM enrichment can be added later as a premium mode for buyer-intent summaries, outreach angles, or account prioritization.
Input
Use companyUrls as the primary input. Public full URLs and bare domains are accepted. Localhost, private-network, and invalid entries are skipped and reported in diagnostics.
{"companyUrls": ["https://www.hubspot.com","https://www.intercom.com"],"country": "United States","maxCompanies": 100,"includeContactEmails": true,"includeLinkedInCompanyUrl": true,"requireContactEmail": false,"requireLinkedInCompanyUrl": false,"requireJobPostingUrl": false,"roleKeywords": ["sales","account executive","customer success","sales engineer"],"maxOpenRolesPerCompany": 25,"minConfidence": 0.75}
Optional discovery mode:
{"searchTerms": ["B2B SaaS companies hiring sales"],"maxCompanies": 25}
Search discovery is optional and less reliable than direct company URLs. For production agent workflows, pass known company URLs.
Invalid or non-public company URL entries do not stop the whole run when at least one usable company URL or search term is present. They are skipped and reported in the Actor output diagnostics. maxCompanies caps accepted company URLs to crawl and returned valid leads.
Clean mode toggles can return only rows that are immediately ready for a specific workflow:
| Toggle | Effect |
|---|---|
requireContactEmail | Return only leads with at least one public contact email. |
requireLinkedInCompanyUrl | Return only leads with a public LinkedIn company URL. |
requireJobPostingUrl | Return only leads with at least one matched public job posting URL. |
Starter Inputs
The examples folder includes validated starter inputs for common buyer workflows:
| File | Use case |
|---|---|
examples/sales-outreach.json | Qualify target accounts for sales outreach using sales, sales engineering, and customer success hiring signals. |
examples/recruiting-demand.json | Find B2B SaaS companies with engineering hiring demand for recruiting, talent research, or market mapping. |
examples/agent-batch-qa.json | Test a messy account list with duplicates, invalid entries, over-limit URLs, runRecommendations, and compact output rows. |
For the first paid run, start with sales-outreach.json and replace companyUrls with your own target account list.
First Run Checklist
Use this for the first Store run or saved task:
- Start with 10 to 25 known B2B SaaS account URLs.
- Pick one workflow: sales outreach, recruiting demand, or agent batch QA.
- Keep
maxOpenRolesPerCompanybetween 3 and 10 so the dataset preview stays readable. - Set
minConfidencebetween0.6and0.75while calibrating your market. - Check
OUTPUT.runRecommendationsfirst, then open the dataset rows for source evidence. - Send only
qualifiedLeadsCompactor dataset rows withsignalStrengthofmediumorstronginto the next agent, CRM, or enrichment step.
Sales outreach:
{"companyUrls": ["https://cursor.com", "https://www.hubspot.com", "https://www.intercom.com"],"country": "United States","maxCompanies": 25,"includeContactEmails": true,"includeLinkedInCompanyUrl": true,"roleKeywords": ["account executive", "sales engineer", "customer success", "sales development"],"maxOpenRolesPerCompany": 5,"minConfidence": 0.7}
Recruiting demand:
{"companyUrls": ["https://cursor.com", "https://www.rippling.com", "https://www.deel.com"],"country": "United States","maxCompanies": 25,"includeContactEmails": false,"includeLinkedInCompanyUrl": true,"roleKeywords": ["software engineer", "product engineer", "backend engineer", "machine learning", "infrastructure"],"maxOpenRolesPerCompany": 10,"minConfidence": 0.65}
Agent batch QA:
{"companyUrls": ["cursor.com", "https://www.cursor.com/pricing", "https://intercom.com", "not a url", "https://overflow.example.com"],"maxCompanies": 2,"includeContactEmails": true,"includeLinkedInCompanyUrl": true,"roleKeywords": ["account executive", "customer success", "engineer"],"maxOpenRolesPerCompany": 3,"minConfidence": 0.6}
Output
Each pushed dataset item is a validated company-level lead.
{"companyName": "HubSpot","websiteUrl": "https://hubspot.com","domain": "hubspot.com","sourceUrl": "https://www.hubspot.com/careers","hiringSignal": "Strong hiring signal found for sales, customer success","signalStrength": "strong","signalSourceType": "careers_page","openRolesCount": 2,"openRoleTitlesReturnedCount": 2,"openRolesTruncated": false,"roleKeywordGroups": [{"keyword": "sales","openRolesCount": 1,"sampleTitles": ["Senior Sales Engineer"]},{"keyword": "customer success","openRolesCount": 1,"sampleTitles": ["Customer Success Manager"]}],"openRoleTitles": ["Senior Sales Engineer", "Customer Success Manager"],"jobPostingUrls": ["https://jobs.example.com/senior-sales-engineer","https://jobs.example.com/customer-success-manager"],"roleKeywords": ["sales", "customer success"],"roleKeywordsText": "sales | customer success","contactEmails": [],"contactEmailsText": "","openRoleTitlesText": "Senior Sales Engineer | Customer Success Manager","jobPostingUrlsText": "https://jobs.example.com/senior-sales-engineer | https://jobs.example.com/customer-success-manager","linkedinCompanyUrl": "https://www.linkedin.com/company/hubspot","qualificationSummary": "HubSpot qualified with strong role signals for sales, customer success, a LinkedIn company URL at 90% confidence.","evidence": [{"type": "hiring_signal","value": "Strong hiring signal found for sales, customer success","sourceUrl": "https://www.hubspot.com/careers"}],"evidenceSummary": "hiring_signal: Strong hiring signal found for sales, customer success (https://www.hubspot.com/careers)","recommendedAction": "Prioritize for sales or recruiting outreach with the cited hiring evidence.","warnings": ["No public contact email found.","Hiring signal is keyword-based and should be verified before outreach."],"warningsText": "No public contact email found. | Hiring signal is keyword-based and should be verified before outreach.","confidence": 0.9,"scrapedAt": "2026-06-28T18:44:36.496Z"}
Spreadsheet preview:
| companyName | domain | confidence | signalStrength | roleKeywordsText | openRoleTitlesText | linkedinCompanyUrl | warningsText |
|---|---|---|---|---|---|---|---|
| HubSpot | hubspot.com | 0.9 | strong | sales | customer success | Senior Sales Engineer | Customer Success Manager | https://www.linkedin.com/company/hubspot | No public contact email found. | Hiring signal is keyword-based and should be verified before outreach. |
The Actor also writes a run-level OUTPUT record for batch workflows:
{"qualifiedLeadsUrl": "https://api.apify.com/v2/datasets/example/items","summary": {"requestedCompanyUrlCount": 2,"acceptedCompanyUrlCount": 1,"searchTermsCount": 0,"maxCompanies": 100,"candidateDomains": 1,"requestsProcessed": 5,"rawLeads": 1,"validLeads": 1,"pushedLeads": 1,"chargeLimitReached": false},"qualifiedLeadsCompact": [{"companyName": "HubSpot","domain": "hubspot.com","websiteUrl": "https://hubspot.com","sourceUrl": "https://www.hubspot.com/careers","confidence": 0.9,"signalStrength": "strong","signalSourceType": "careers_page","openRolesCount": 2,"openRoleTitlesReturnedCount": 2,"openRolesTruncated": false,"roleKeywordsText": "sales | customer success","openRoleTitlesText": "Senior Sales Engineer | Customer Success Manager","jobPostingUrlsText": "https://jobs.example.com/senior-sales-engineer | https://jobs.example.com/customer-success-manager","linkedinCompanyUrl": "https://www.linkedin.com/company/hubspot","qualificationSummary": "HubSpot qualified with strong role signals for sales, customer success, a LinkedIn company URL at 90% confidence.","recommendedAction": "Prioritize for sales or recruiting outreach with the cited hiring evidence.","scrapedAt": "2026-06-28T18:44:36.496Z"}],"runRecommendations": {"totalCompanyStatuses": 3,"billableLeadCount": 1,"retryableCount": 1,"flows": [{"nextActionType": "use_qualified_lead","count": 1,"billableLeadAvailable": true,"retryable": false,"inputUrls": ["https://hubspot.com"],"domains": ["hubspot.com"]},{"nextActionType": "review_non_qualified_company","count": 1,"billableLeadAvailable": false,"retryable": false,"inputUrls": ["https://example.com"],"domains": ["example.com"]},{"nextActionType": "fix_input_url","count": 1,"billableLeadAvailable": false,"retryable": true,"inputUrls": ["bad value"],"domains": []}]},"diagnostics": {"requestedCompanyUrlCount": 2,"acceptedCompanyUrlCount": 1,"invalidCompanyUrls": ["bad value"],"duplicateCompanyDomains": [],"skippedCompanyUrlsOverMaxCompanies": [],"companyStatuses": [{"inputUrl": "https://hubspot.com","status": "qualified","domain": "hubspot.com","websiteUrl": "https://hubspot.com","companyName": "HubSpot","nextAction": {"type": "use_qualified_lead","billableLeadAvailable": true,"retryable": false}},{"inputUrl": "https://example.com","status": "not_qualified","domain": "example.com","websiteUrl": "https://example.com","reason": "no_matching_hiring_signal","pagesProcessed": 5,"failedRequests": 0,"nextAction": {"type": "review_non_qualified_company","billableLeadAvailable": false,"retryable": false}},{"inputUrl": "bad value","status": "input_skipped","reason": "invalid_url","nextAction": {"type": "fix_input_url","billableLeadAvailable": false,"retryable": true}}],"nonQualifiedCompanies": [{"domain": "example.com","websiteUrl": "https://example.com","reason": "no_matching_hiring_signal","pagesProcessed": 5,"failedRequests": 0}]}}
Output Fields
| Field | Meaning |
|---|---|
companyName | Normalized company name. |
websiteUrl | Normalized company website origin. |
domain | Deduplication key. |
sourceUrl | Page where the strongest qualifying evidence was found. |
hiringSignal | Human-readable hiring or growth signal. |
signalStrength | Signal quality tier: strong, medium, or weak. Billable leads require non-weak hiring evidence. |
signalSourceType | Type of source page: job_board, careers_page, company_page, or homepage. |
jobBoardProvider | Detected provider for known public job boards such as Greenhouse, Lever, Ashby, or Workable. |
openRoleTitles | Matched public role titles extracted from job board links, individual job pages, or careers page links. |
jobPostingUrls | Public URLs for matched role postings. |
openRolesCount | Count of matched public roles when available, otherwise matched role keyword groups. |
openRoleTitlesReturnedCount | Number of role titles returned after applying maxOpenRolesPerCompany. |
openRolesTruncated | Whether more matched roles exist than were returned in openRoleTitles and jobPostingUrls. |
roleKeywordGroups | Grouped role summary by configured role keyword with counts and sample titles. |
roleKeywords | Matched role/function keywords. |
roleKeywordsText | Pipe-separated matched role keywords for CSV, Excel, Google Sheets, and CRM imports. |
contactEmails | Public company emails found on crawled pages. |
contactEmailsText | Pipe-separated public company emails for CSV, Excel, Google Sheets, and CRM imports. |
openRoleTitlesText | Pipe-separated matched role titles for CSV, Excel, Google Sheets, and CRM imports. |
jobPostingUrlsText | Pipe-separated matched job posting URLs for CSV, Excel, Google Sheets, and CRM imports. |
linkedinCompanyUrl | Public LinkedIn company URL found on the website. |
qualificationSummary | Short explanation for AI agents and operators. |
evidence | Structured source-backed evidence items. |
evidenceSummary | Pipe-separated source evidence summary for spreadsheet review and no-code tools. |
recommendedAction | Suggested next workflow step. |
warnings | Quality or verification caveats. |
warningsText | Pipe-separated quality caveats for spreadsheet review and no-code tools. |
confidence | Deterministic confidence score from 0 to 1. |
scrapedAt | ISO timestamp for the crawl. |
Run Diagnostics
The OUTPUT record is intended for AI agents and batch automations that need to decide what happened after a run without reading every dataset row.
| Field | Meaning |
|---|---|
qualifiedLeadsUrl | API URL for the default dataset items. |
summary.requestedCompanyUrlCount | Number of company URL entries submitted. |
summary.acceptedCompanyUrlCount | Number of unique company domains accepted for crawling after validation, deduplication, and maxCompanies. |
summary.validLeads | Number of company-level leads that passed validation. |
summary.pushedLeads | Number of leads written to the dataset before any charge limit stopped writes. |
summary.chargeLimitReached | Whether Apify pay-per-event charge capping stopped dataset writes. |
qualifiedLeadsCompact | Flat, spreadsheet-friendly summary rows for valid leads. Multi-value fields are joined with a pipe separator so each row can map cleanly to CSV or CRM columns. |
runRecommendations | Agent-ready aggregate of next-action flows, including counts, retryability, billable lead availability, input URLs, and domains by action type. |
diagnostics.invalidCompanyUrls | Submitted company URL entries that could not be normalized into public HTTP(S) company URLs. |
diagnostics.duplicateCompanyDomains | Duplicate company domains skipped before crawling. |
diagnostics.skippedCompanyUrlsOverMaxCompanies | Usable company URL entries skipped because maxCompanies had already been reached. |
diagnostics.companyStatuses | Per-submission routing list for agent workflows. Status values are qualified, not_qualified, and input_skipped; reasons include invalid URL, duplicate domain, over max companies, no matching hiring signal, not crawled, crawl failed, and blocked by security. |
diagnostics.companyStatuses[].nextAction | Machine-readable routing recommendation. Action types include use_qualified_lead, review_non_qualified_company, fix_input_url, use_original_domain_result, increase_max_companies, and retry_crawl. |
diagnostics.nonQualifiedCompanies | Accepted company domains that were crawled but did not become valid leads. Reasons include no_matching_hiring_signal, not_crawled, crawl_failed, and blocked_by_security. |
What You Pay For
The paid unit is a validated account qualification result, not every submitted URL. A validLead is charged only when the Actor finds a company with non-weak hiring evidence, matched role keywords, source evidence, and a validated dataset row.
Invalid URLs, duplicate domains, over-limit URLs, and companies that do not qualify are still reported in OUTPUT diagnostics and runRecommendations, but they are not charged as validLead events. Apify platform usage and the Actor start event may still apply according to the Store pricing settings.
Pricing Unit
Recommended pay-per-event unit:
validLead
The Actor calls Actor.pushData(lead, "validLead") so the paid event is tied to the dataset write. The event name is defined in src/monetization.ts and covered by tests to avoid accidental pricing drift.
Active Store price:
$10.00 per 1,000 valid leads
Limits
- This Actor does not scrape logged-in LinkedIn pages.
- Public emails are extracted only from company pages crawled by the Actor.
- Hiring signals are keyword-based and should be verified before outreach.
- Search discovery is available, but direct company URL qualification is the stronger product path.
Troubleshooting
| Symptom | Most likely reason | What to do |
|---|---|---|
No validLead rows | Company pages did not expose public hiring evidence matching your roleKeywords. | Lower minConfidence, broaden roleKeywords, or use known careers/job-board URLs as company sources. |
| Company appears in diagnostics only | The URL was invalid, duplicated, over maxCompanies, blocked by network safety, or crawled without qualifying signals. | Check OUTPUT.diagnostics.companyStatuses for the exact reason and next action. |
| Missing emails or job URLs | The company did not publish those fields on crawled public pages, or the roles are rendered behind unsupported JavaScript. | Use the lead anyway when confidence and evidence are strong, or rerun with a direct public job-board URL. |
Quality Benchmark
The repository includes a local benchmark workflow for measuring whether the Actor is improving over time.
Run it from the portfolio root:
pnpm b2b:benchmarkpnpm b2b:benchmark:buyer
Named benchmark inputs:
| Name | File | Purpose |
|---|---|---|
smoke | benchmark/b2b-saas-accounts.json | Fast 10-company regression check. |
buyer-validation | benchmark/b2b-saas-buyer-validation.json | Larger 25-company product quality check. |
You can also pass a direct JSON path to pnpm --filter b2b-saas-lead-qualifier benchmark <path>.
The script writes run artifacts to data/b2b-saas-lead-qualifier/benchmark/<timestamp>/:
| File | Purpose |
|---|---|
summary.json | Buyer-facing quality metrics: valid lead rate, accepted lead rate, average confidence, failure reasons, provider coverage, and request efficiency. |
output.json | Full run-level OUTPUT record with diagnostics and recommendations. |
leads.json | Full qualified lead records returned by the crawler. |
stats.json | Raw crawler statistics. |
Latest local snapshot from the default 10-company benchmark:
| Metric | Value |
|---|---|
| Valid lead rate | 100% |
| Accepted lead rate | 100% |
| Valid leads | 10 / 10 |
| Average confidence | 0.88 |
| Strong signal rate | 90% |
| Requests per accepted company | 19.9 |
| Runtime | 13.005 seconds |
There were no non-qualified companies in that run. Treat these snapshots as directional because public websites and job boards change over time.
Latest local snapshot from the 25-company buyer-validation benchmark:
| Metric | Value |
|---|---|
| Valid lead rate | 92% |
| Accepted lead rate | 92% |
| Valid leads | 23 / 25 |
| Average confidence | 0.8935 |
| Strong signal rate | 82.61% |
| Requests per accepted company | 19.16 |
| Runtime | 66.033 seconds |
The remaining non-qualified companies in that run were Confluent and Canva. Confluent was classified as blocked_by_security and routed to retry_crawl; Canva was classified as no_matching_hiring_signal.
Local Development
From the portfolio root:
pnpm b2b:testpnpm b2b:typecheckpnpm b2b:samplepnpm b2b:benchmark
Actor-local commands:
pnpm testpnpm typecheckpnpm samplepnpm benchmark
The sample script uses a separate storage-live-sample local storage directory so it does not conflict with apify run.
The benchmark script uses storage-benchmark and writes generated artifacts under the repo-level data/ folder.
Apify CLI checks from the Actor folder:
npx apify-cli validate-schemanpx apify-cli run
Docker build check from the Actor folder:
$docker build -f .actor/Dockerfile -t b2b-saas-lead-qualifier:local .
Deployment check from the Actor folder:
$npx apify-cli push --wait-for-finish=300