B2B SaaS Account Qualifier for AI Agents avatar

B2B SaaS Account Qualifier for AI Agents

Pricing

from $10.00 / 1,000 valid leads

Go to Apify Store
B2B SaaS Account Qualifier for AI Agents

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

DeepAPI

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

0

Monthly active users

4 days ago

Last modified

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:

ToggleEffect
requireContactEmailReturn only leads with at least one public contact email.
requireLinkedInCompanyUrlReturn only leads with a public LinkedIn company URL.
requireJobPostingUrlReturn only leads with at least one matched public job posting URL.

Starter Inputs

The examples folder includes validated starter inputs for common buyer workflows:

FileUse case
examples/sales-outreach.jsonQualify target accounts for sales outreach using sales, sales engineering, and customer success hiring signals.
examples/recruiting-demand.jsonFind B2B SaaS companies with engineering hiring demand for recruiting, talent research, or market mapping.
examples/agent-batch-qa.jsonTest 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:

  1. Start with 10 to 25 known B2B SaaS account URLs.
  2. Pick one workflow: sales outreach, recruiting demand, or agent batch QA.
  3. Keep maxOpenRolesPerCompany between 3 and 10 so the dataset preview stays readable.
  4. Set minConfidence between 0.6 and 0.75 while calibrating your market.
  5. Check OUTPUT.runRecommendations first, then open the dataset rows for source evidence.
  6. Send only qualifiedLeadsCompact or dataset rows with signalStrength of medium or strong into 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:

companyNamedomainconfidencesignalStrengthroleKeywordsTextopenRoleTitlesTextlinkedinCompanyUrlwarningsText
HubSpothubspot.com0.9strongsales | customer successSenior Sales Engineer | Customer Success Managerhttps://www.linkedin.com/company/hubspotNo 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

FieldMeaning
companyNameNormalized company name.
websiteUrlNormalized company website origin.
domainDeduplication key.
sourceUrlPage where the strongest qualifying evidence was found.
hiringSignalHuman-readable hiring or growth signal.
signalStrengthSignal quality tier: strong, medium, or weak. Billable leads require non-weak hiring evidence.
signalSourceTypeType of source page: job_board, careers_page, company_page, or homepage.
jobBoardProviderDetected provider for known public job boards such as Greenhouse, Lever, Ashby, or Workable.
openRoleTitlesMatched public role titles extracted from job board links, individual job pages, or careers page links.
jobPostingUrlsPublic URLs for matched role postings.
openRolesCountCount of matched public roles when available, otherwise matched role keyword groups.
openRoleTitlesReturnedCountNumber of role titles returned after applying maxOpenRolesPerCompany.
openRolesTruncatedWhether more matched roles exist than were returned in openRoleTitles and jobPostingUrls.
roleKeywordGroupsGrouped role summary by configured role keyword with counts and sample titles.
roleKeywordsMatched role/function keywords.
roleKeywordsTextPipe-separated matched role keywords for CSV, Excel, Google Sheets, and CRM imports.
contactEmailsPublic company emails found on crawled pages.
contactEmailsTextPipe-separated public company emails for CSV, Excel, Google Sheets, and CRM imports.
openRoleTitlesTextPipe-separated matched role titles for CSV, Excel, Google Sheets, and CRM imports.
jobPostingUrlsTextPipe-separated matched job posting URLs for CSV, Excel, Google Sheets, and CRM imports.
linkedinCompanyUrlPublic LinkedIn company URL found on the website.
qualificationSummaryShort explanation for AI agents and operators.
evidenceStructured source-backed evidence items.
evidenceSummaryPipe-separated source evidence summary for spreadsheet review and no-code tools.
recommendedActionSuggested next workflow step.
warningsQuality or verification caveats.
warningsTextPipe-separated quality caveats for spreadsheet review and no-code tools.
confidenceDeterministic confidence score from 0 to 1.
scrapedAtISO 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.

FieldMeaning
qualifiedLeadsUrlAPI URL for the default dataset items.
summary.requestedCompanyUrlCountNumber of company URL entries submitted.
summary.acceptedCompanyUrlCountNumber of unique company domains accepted for crawling after validation, deduplication, and maxCompanies.
summary.validLeadsNumber of company-level leads that passed validation.
summary.pushedLeadsNumber of leads written to the dataset before any charge limit stopped writes.
summary.chargeLimitReachedWhether Apify pay-per-event charge capping stopped dataset writes.
qualifiedLeadsCompactFlat, 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.
runRecommendationsAgent-ready aggregate of next-action flows, including counts, retryability, billable lead availability, input URLs, and domains by action type.
diagnostics.invalidCompanyUrlsSubmitted company URL entries that could not be normalized into public HTTP(S) company URLs.
diagnostics.duplicateCompanyDomainsDuplicate company domains skipped before crawling.
diagnostics.skippedCompanyUrlsOverMaxCompaniesUsable company URL entries skipped because maxCompanies had already been reached.
diagnostics.companyStatusesPer-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[].nextActionMachine-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.nonQualifiedCompaniesAccepted 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

SymptomMost likely reasonWhat to do
No validLead rowsCompany 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 onlyThe 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 URLsThe 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:benchmark
pnpm b2b:benchmark:buyer

Named benchmark inputs:

NameFilePurpose
smokebenchmark/b2b-saas-accounts.jsonFast 10-company regression check.
buyer-validationbenchmark/b2b-saas-buyer-validation.jsonLarger 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>/:

FilePurpose
summary.jsonBuyer-facing quality metrics: valid lead rate, accepted lead rate, average confidence, failure reasons, provider coverage, and request efficiency.
output.jsonFull run-level OUTPUT record with diagnostics and recommendations.
leads.jsonFull qualified lead records returned by the crawler.
stats.jsonRaw crawler statistics.

Latest local snapshot from the default 10-company benchmark:

MetricValue
Valid lead rate100%
Accepted lead rate100%
Valid leads10 / 10
Average confidence0.88
Strong signal rate90%
Requests per accepted company19.9
Runtime13.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:

MetricValue
Valid lead rate92%
Accepted lead rate92%
Valid leads23 / 25
Average confidence0.8935
Strong signal rate82.61%
Requests per accepted company19.16
Runtime66.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:test
pnpm b2b:typecheck
pnpm b2b:sample
pnpm b2b:benchmark

Actor-local commands:

pnpm test
pnpm typecheck
pnpm sample
pnpm 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-schema
npx 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