ICP Fit Scorer
Pricing
from $50.00 / 1,000 results
ICP Fit Scorer
Scores pre-enriched companies against your Ideal Customer Profile using weighted signals. Returns a 0 to 100 fit score, A to D tier, and per-signal breakdown. Deterministic and LLM modes. Built for Clay enrichment and batch processing. MCP-ready for Claude Desktop and AI agents.
Pricing
from $50.00 / 1,000 results
Rating
0.0
(0)
Developer
Mamba Labs
Maintained by CommunityActor stats
0
Bookmarked
3
Total users
2
Monthly active users
4 days ago
Last modified
Categories
Share
Scores companies against your ICP using weighted signals. Returns icp_score 0-100, icp_tier A-D, and a per-signal breakdown. Works with plain-English ICP descriptions or a custom JSON config.
What's New
- Clay table template available. Pre-built table with 13 input columns, enrichment column, and 17 formula columns including ISBLANK wrappers for score fields. Open the template →
- v1.1.6 fixes. Invalid scoring_config keys (gtm_role_count_above_10, signal_strength_high, funding_match) now log a warning instead of silently scoring 0. Actor.log.error crash fixed across all call sites. Input schema updated for Clay string coercion compatibility.
Two ways to set up scoring
JSON config mode. Define exact weights per signal in a scoring_config object. Deterministic, auditable, no API key needed. You control exactly how much each signal is worth. Best for teams that have already defined their ICP criteria.
Plain-English mode. Describe your ICP in a sentence or two and provide an OpenAI or Anthropic API key. The actor calls GPT-4o-mini or Claude Haiku to generate a valid scoring_config automatically. Best for non-technical users who want to score leads without writing JSON.
If you provide both, the JSON config wins and the LLM call is skipped.
How it works
Pass in pre-enriched company data (hiring signals, tech stack, headcount, funding, industry) along with a scoring config or ICP description. The actor evaluates each signal as true or false, applies the configured weights, and returns a score from 0 to 100 with a tier label.
No live scraping. No waiting for website crawls. Input data comes from Clay enrichment columns or from Actors 1 and 2 in the Mamba Labs suite. Scoring is fast and deterministic in JSON config mode.
The Actor 1 + 2 + 6 workflow
Actor 6 input fields map directly to Actor 1 and Actor 2 output column names. This is intentional. Run them in sequence in Clay and pass outputs directly into Actor 6 with no column remapping.
Step 1: Run Actor 1 (GTM Hiring Signal Scraper) on your company list. It returns:
gtm_hiring_signal(boolean): map to Actor 6 inputgtm_hiring_signalgtm_role_count(integer): map to Actor 6 inputgtm_role_countsignal_strength(string: high/medium/low): map to Actor 6 inputsignal_strength
Step 2: Run Actor 2 (GTM Tech Stack Signal Scraper) on the same company list. It returns:
uses_hubspot(boolean): map to Actor 6 inputuses_hubspotuses_salesforce(boolean): map to Actor 6 inputuses_salesforceuses_clay(boolean): map to Actor 6 inputuses_claycrm_detected(string): map to Actor 6 inputcrm_detectedseq_tool_detected(string): map to Actor 6 inputseq_tool_detected
Step 3: Add Clay native enrichment columns for headcount, funding_stage, and industry. These are standard Clay enrichment fields, not actor outputs.
Step 4: Run Actor 6 (this actor). Pass all the above as input fields using Clay's column token system. Set your scoring_config weights to reflect how much each signal matters for your ICP.
Step 5: Filter your Clay table on icp_tier = A or lead_tag = priority to get your send-ready list.
No other ICP scorer on the Apify Store is designed to receive these specific field names as input. This workflow is the fastest path from company list to scored outbound queue.
scoring_config format
The scoring_config object has three parts:
weights: maps signal names to integer point values. Must sum to exactly 100.headcount_range: an object withminandmaxfor the headcount_in_range signal.target_industries: an array of industry strings for the industry_match signal.
Full example:
{"scoring_config": {"weights": {"gtm_hiring_signal": 25,"uses_hubspot": 15,"uses_clay": 10,"headcount_in_range": 20,"recently_funded": 15,"industry_match": 15},"headcount_range": { "min": 50, "max": 500 },"target_industries": ["B2B Software", "SaaS", "Developer Tools"]}}
Minimal 2-signal config:
{"scoring_config": {"weights": {"gtm_hiring_signal": 60,"headcount_in_range": 40},"headcount_range": { "min": 100, "max": 1000 }}}
Available signal keys: gtm_hiring_signal, uses_hubspot, uses_salesforce, uses_clay, crm_detected, seq_tool_detected, headcount_in_range, recently_funded, industry_match. Pick the ones that matter and distribute 100 points across them.
Input schema
Provide either scoring_config or icp_description. One of the two is required.
| Field | Type | Required | Description |
|---|---|---|---|
company_domain | string | Yes | Primary domain of the company to score. |
scoring_config | object | No | JSON scoring weights config. Required if icp_description is not provided. |
template | string | No | Pre-built template: saas_outbound, b2b_services, fintech, smb_local, enterprise. |
icp_description | string | No | Plain-English ICP description. Requires llm_api_key. |
llm_api_key | string | No | OpenAI or Anthropic API key. Required for icp_description mode. Masked in Apify UI. |
llm_provider | string | No | "openai" (default) or "anthropic". Ignored if scoring_config is provided. |
company_name | string | No | Display name of the company. |
gtm_hiring_signal | boolean | No | Whether the company is hiring GTM roles. |
uses_hubspot | boolean | No | HubSpot detected. |
uses_salesforce | boolean | No | Salesforce detected. |
uses_clay | boolean | No | Clay detected. |
crm_detected | string | No | CRM platform detected. |
seq_tool_detected | string | No | Sequencing tool detected. |
headcount | integer | No | Current employee count. |
funding_stage | string | No | Funding stage (seed, series_a, series_b, growth). |
industry | string | No | The company's industry. |
previous_score | integer | No | ICP score from a prior run. Enables delta tracking. |
include_explanation | boolean | No | Add a score_explanation string to output. Default false. |
min_score_to_output | integer | No | Skip rows below this threshold. |
webhook_url | string | No | POST each result to this URL after scoring. |
Output schema
| Field | Type | Description |
|---|---|---|
company_domain | string | Domain that was scored. |
company_name | string | Company display name. |
icp_score | integer | Final score 0-100. |
icp_tier | string | A (80-100), B (60-79), C (40-59), D (0-39). |
lead_tag | string | priority (A), nurture (B/C), disqualify (D). |
score_hiring | integer | Points from hiring signals. |
score_tech_stack | integer | Points from tech stack signals. |
score_headcount | integer | Points from headcount signal. |
score_funding | integer | Points from funding signal. |
score_industry | integer | Points from industry signal. |
signals_matched | string | Comma-separated signal keys that matched. |
signals_missing | string | Comma-separated signal keys that did not match. |
scoring_config_used | string | JSON string of the config applied. |
config_source | string | "explicit" (JSON config) or "llm_generated" (from icp_description). |
previous_score | integer | Echoed from input. Null if not provided. |
score_delta | integer | Current score minus previous score. Null if no previous. |
score_direction | string | "improving" (delta > 0), "declining" (delta < 0), "unchanged" (delta = 0), "no_previous". |
score_explanation | string | Human-readable breakdown. Present when include_explanation is true. |
run_date | string | ISO timestamp. |
error | string | Error message if scoring failed. |
Tracking score changes over time
This is the only ICP scorer on the Apify Store that tracks score change per company across runs.
Store icp_score from each run in your Clay table. On the next run, pass it as previous_score. The output includes score_delta (integer, can be negative) and score_direction ("improving", "declining", "unchanged", or "no_previous"). Use score_direction = improving as a trigger for outbound timing, or filter on score_delta > 10 to surface companies that just crossed a scoring threshold.
lead_tag values
Every output row includes a lead_tag field derived automatically from icp_tier. Values: "priority" for tier A, "nurture" for tier B or C, "disqualify" for tier D. Use these directly in Clay view filters, Instantly segment conditions, or Smartlead campaign triggers without writing a formula column.
Sample output
JSON config mode with delta:
{"company_domain": "linear.app","company_name": "Linear","icp_score": 80,"icp_tier": "A","lead_tag": "priority","score_hiring": 30,"score_tech_stack": 0,"score_headcount": 25,"score_funding": 25,"score_industry": 0,"signals_matched": "gtm_hiring_signal, headcount_in_range, recently_funded","signals_missing": "uses_hubspot","scoring_config_used": "{\"weights\":{\"gtm_hiring_signal\":30,\"uses_hubspot\":20,\"headcount_in_range\":25,\"recently_funded\":25},\"headcount_range\":{\"min\":50,\"max\":500}}","config_source": "explicit","previous_score": 65,"score_delta": 15,"score_direction": "improving","run_date": "2026-04-15T12:00:00.000Z"}
LLM-generated config mode:
{"company_domain": "ramp.com","company_name": "Ramp","icp_score": 55,"icp_tier": "C","lead_tag": "nurture","score_hiring": 20,"score_tech_stack": 15,"score_headcount": 20,"score_funding": 0,"score_industry": 0,"signals_matched": "gtm_hiring_signal, uses_hubspot, headcount_in_range","signals_missing": "recently_funded, industry_match","scoring_config_used": "{\"weights\":{\"gtm_hiring_signal\":20,\"uses_hubspot\":15,\"headcount_in_range\":20,\"recently_funded\":25,\"industry_match\":20},\"headcount_range\":{\"min\":100,\"max\":1000},\"target_industries\":[\"B2B Software\",\"SaaS\",\"Fintech\"]}","config_source": "llm_generated","previous_score": null,"score_delta": null,"score_direction": "no_previous","run_date": "2026-04-15T12:00:00.000Z"}
Clay Table Template
A pre-built Clay table template is available with the enrichment column, formula columns, and views ready to use.
The template includes:
- 13 input columns mapped to Actor 1, Actor 2, and Clay native enrichment outputs
- A Run Apify Actor enrichment column with 13 pill inputs plus static target_industries and scoring_config
- 17 output formula columns with ISBLANK wrappers on score fields
- 7 sample companies scored against a SaaS-focused ICP config
Template columns
Input columns (13 columns, your source data):
| Column | Description |
|---|---|
| Company Name | Company display name. Echoed in output. |
| Company Domain | Bare domain, e.g. stripe.com. The only required field. |
| GTM Hiring Signal | "true" or "false". From Actor 1 (GTM Hiring Signal Scraper) output. |
| GTM Role Count | Number of GTM roles found. From Actor 1 output. |
| Signal Strength | "high", "medium", or "low". From Actor 1 or Actor 2 output. |
| Uses HubSpot | "true" or "false". From Actor 2 (GTM Tech Stack Signal Scraper) output. |
| Uses Salesforce | "true" or "false". From Actor 2 output. |
| Uses Clay | "true" or "false". From Actor 2 output. |
| CRM Detected | CRM platform name (e.g. "Salesforce", "HubSpot") or empty. From Actor 2. |
| Seq Tool Detected | Sequencing tool name (e.g. "Outreach", "Apollo") or empty. From Actor 2. |
| Headcount | Company employee count. From Clay native enrichment or any headcount source. |
| Funding Stage | Exact format required: seed, series_a, series_b, series_d, series_i, growth, public, unknown. Case and format matter. See critical setup rules below. |
| Industry | Industry string. From Clay native enrichment. |
Enrichment column (1 column):
| Column | Description |
|---|---|
| Run Apify Actor | Calls mambalabs/icp-fit-scorer with all 13 input columns as pills, plus static target_industries and scoring_config values. Returns raw JSON result. |
Output formula columns (17 columns, extracted from Run Apify Actor):
| Column | Description |
|---|---|
| ICP Score | 0-100 weighted score. Uses ISBLANK wrapper so 0 displays as "0", not blank. |
| ICP Tier | A (80-100), B (60-79), C (40-59), D (0-39). |
| Lead Tag | "priority" (A), "nurture" (B), "monitor" (C), "disqualify" (D). |
| Score Hiring | Points earned from gtm_hiring_signal. ISBLANK wrapped. |
| Score Tech Stack | Points earned from uses_hubspot + uses_clay combined. ISBLANK wrapped. |
| Score Headcount | Points earned from headcount range match. ISBLANK wrapped. |
| Score Funding | Points earned from funding stage match. ISBLANK wrapped. |
| Score Industry | Points earned from industry match. ISBLANK wrapped. |
| Signals Matched | Comma-separated list of signals that scored points, with clean display names (e.g. "GTM Hiring Signal, HubSpot, Clay, Headcount, Funding, Industry"). |
| Signals Missing | Comma-separated list of signals with no data, with clean display names. |
| Score Explanation | LLM-generated explanation. Only populated in LLM mode with include_explanation enabled. Empty in deterministic mode. |
| Config Source | "explicit" (JSON config), "template" (preset), or "llm" (LLM mode). |
| Score Delta | Difference from previous_score. Only populated when previous_score is provided. |
| Previous Score | The previous score passed in for delta comparison. Only populated when provided. |
| Score Direction | "improving", "declining", "stable", "new", or "no_previous". |
| Error | Error message if the actor failed on this row. Empty on success. |
| Run Date | ISO timestamp of when the actor processed this row. |
Columns that will be empty in the template (and why):
Score Explanation is only populated in LLM mode. The template uses deterministic scoring_config mode. Score Delta and Previous Score are only populated when you pass a previous_score input, and the template rows are first-run scores with no previous score to compare. Error is empty when everything works correctly.
How to use this template
- Open the template link and clone it to your Clay workspace.
- Delete the 7 sample rows or keep them for reference.
- Import your own company list. At minimum, populate the Company Domain column. All other input columns are optional.
- Populate input columns from other sources. Run Actor 1 (GTM Hiring Signal Scraper) to get GTM Hiring Signal, GTM Role Count, Signal Strength. Run Actor 2 (GTM Tech Stack Signal Scraper) to get Uses HubSpot, Uses Salesforce, Uses Clay, CRM Detected, Seq Tool Detected. Use Clay native enrichment for Headcount and Industry. Funding Stage must be manually added or pulled from a funding data source in exact lowercase format (series_a, series_b, etc.).
- Edit the scoring_config in the Run Apify Actor enrichment column if your ICP differs from the template default (SaaS companies, 50-500 headcount, recently funded, using HubSpot or Clay).
- Edit the target_industries string if your target industries differ.
- Run the enrichment column on all rows.
- Sort or filter by ICP Score or ICP Tier to prioritize your outbound list.
Setting up the Run Apify Actor column from scratch
If building your own table instead of cloning the template, here is how to configure the enrichment column.
- Add a "Run Apify Actor" column from Clay's enrichment menu.
- Set the Actor ID to:
mambalabs/icp-fit-scorer - In the Input Data field, build this JSON. Type each key in quotes (these are the actor's input field names, lowercase snake_case). For values, type
/to insert a column pill. Do NOT type column names manually as string values.
{"company_domain": "/Company Domain pill/","company_name": "/Company Name pill/","gtm_hiring_signal": "/GTM Hiring Signal pill/","gtm_role_count": "/GTM Role Count pill/","signal_strength": "/Signal Strength pill/","uses_hubspot": "/Uses HubSpot pill/","uses_salesforce": "/Uses Salesforce pill/","uses_clay": "/Uses Clay pill/","crm_detected": "/CRM Detected pill/","seq_tool_detected": "/Seq Tool Detected pill/","headcount": "/Headcount pill/","funding_stage": "/Funding Stage pill/","industry": "/Industry pill/","target_industries": "SaaS, Software Development, Information Technology","scoring_config": {"weights":{"gtm_hiring_signal":25,"uses_hubspot":15,"uses_clay":10,"headcount_in_range":20,"recently_funded":15,"industry_match":15},"headcount_range":{"min":50,"max":500},"funded_within_days":365}}
Where /Column Name pill/ means: type ", then hit /, search for that column name, click the pill, then type " to close the quotes. The last two fields (target_industries and scoring_config) are static values typed exactly as shown, not column pills.
Critical setup rules
These will break your table if ignored.
1. Wrap every pill value in double quotes. Type " before and after each pill. Without quotes, Clay sends bare values (e.g. stripe.com instead of "stripe.com") and JSON parsing fails on Apify's side.
2. target_industries is a comma-separated string, not a JSON array. The actor's input schema declares this as type string. Write "target_industries": "SaaS, Software Development, Information Technology" not "target_industries": ["SaaS", "Software Development"].
3. Toggle OFF optional pills. Every pill has a blue toggle switch. Turn OFF the toggle for every pill except Company Domain. When the toggle is ON and a cell is empty, Clay blocks the entire request with "Some inputs missing." The actor handles null fields correctly on its end (scores 0, lists the signal in signals_missing), but Clay never lets the request reach the actor if a toggled-on pill points to an empty cell.
4. Do not use formula mode or JSON data mode for the Input Data field. It does not work with Run Apify Actor. Use pill mode only (type / to insert column references).
5. Funding Stage must be in exact lowercase format. The actor expects: seed, series_a, series_b, series_d, series_i, growth, public, unknown. If your data has "Series B" or "Series D", the recently_funded signal will not match and will show up in Signals Missing. Normalize your data before running.
6. Score columns need ISBLANK wrappers. Clay treats integer 0 as blank. Formula columns that extract score values (ICP Score, Score Hiring, Score Tech Stack, Score Headcount, Score Funding, Score Industry) need IF(ISBLANK(value), "0", value) so that a legitimate score of 0 displays as "0" instead of an empty cell.
Pricing
$0.05 per result. Pay per event, billed per domain processed. No subscription, no seat license, no contract.
| Volume | Cost |
|---|---|
| 100 domains | $5.00 |
| 1,000 domains | $50.00 |
| 10,000 domains | $500.00 |
We recently reduced pricing across the Mamba Labs actor suite to bring more value to GTM teams running enrichment at scale.
LLM mode uses your own OpenAI (GPT-4o-mini) or Anthropic (Claude Haiku) API key, approximately $0.001 to $0.003 per call billed directly to your API provider. JSON config mode has no LLM cost. Your key is masked in the Apify UI and redacted from run logs.
Known Limitations
- JSON config mode is fully deterministic. LLM mode may produce slightly different scoring_config interpretations for the same description across runs.
- scoring_config weights must sum to 100. The actor returns an error if they do not. Unrecognized signal keys are logged as warnings and skipped, they do not cause errors.
- Pre-enriched input only: this actor does not fetch signals on its own. Run Actors 1 and 2 first, or use the fetch_signals option with an Apify token.
- signals_missing will be populated for any input field that was null or absent. Review this field to identify data gaps before treating scores as final.
- signals_missing can misclassify present-but-false fields. When a boolean field like uses_hubspot is explicitly passed as "false", it may appear in signals_missing even though the field was provided and evaluated correctly. This does not affect scoring (the signal correctly scores 0), but the signals_missing list can be misleading.
- funding_stage requires exact format and is not normalized. "Series B" does not match, only "series_b" works. Same for all funding stages. Normalize your data in Clay with a formula column or find-and-replace before passing it to the actor.
- In LLM mode, the error message when neither scoring_config nor icp_description is provided says "Either scoring_config or template is required." It should say "Either scoring_config or icp_description is required."
Issues and Feature Requests
Found a bug or want to request a feature? Open an issue in the Issues tab above. Response time: typically within 48 hours.
Related Actors
All Mamba Labs actors output flat, Clay-ready JSON. Use them together or individually.
- GTM Hiring Signal Scraper, $0.05/result. Detects GTM hiring activity on Greenhouse, Lever, and Ashby. Returns role counts, signal tags, and velocity tracking.
- GTM Tech Stack Signal Enrichment, $0.015/result. Detects CRM, sequencer, and marketing automation from a company's public-facing scripts. Flat boolean output.
- GTM Signals Aggregator, $0.09/result. Runs hiring and tech stack detection in one call. Returns a composite score, recommended action, and plain-English summary.
- Job Board Keyword Signal Scanner, $0.05/result. Scans Greenhouse, Lever, Ashby, Workday, and Rippling for any role category you define. GTM, Engineering, Finance, or custom keywords.
- Domain to LinkedIn URL Resolver, $0.006/result. Resolves company domains to LinkedIn URLs with confidence scoring, firmographics, and social links in one flat row.
Use with MCP (AI Agents)
This actor is callable as a tool over MCP (Model Context Protocol) by AI clients like Claude Desktop, Cursor, VS Code (GitHub Copilot), Windsurf, and any other MCP-compatible client. Apify hosts the MCP server at mcp.apify.com, so no custom server code is needed.
What this actor does in an MCP context
Scores a single company against your ICP criteria and returns a numeric fit score from 0 to 100 along with a per-signal breakdown, a tier label (A-D), and a lead tag. It is the qualification step that sits at the end of the Mamba Labs GTM pipeline, after the data-collection actors have populated hiring, tech stack, headcount, and funding fields.
Example prompts:
- "Score how well stripe.com fits my ICP using these weights: gtm_hiring_signal 30, uses_hubspot 20, headcount_in_range 25, recently_funded 25."
- "Rate Linear against my ideal customer profile of B2B SaaS companies with 50 to 500 employees that recently raised funding."
- "Is ramp.com a good fit based on these criteria: uses HubSpot, hiring GTM roles, headcount 100 to 1000?"
Supported MCP clients
Claude Desktop, Cursor, VS Code (GitHub Copilot), Windsurf, and any MCP-compatible client.
Setup: Hosted server (recommended)
Add this entry to your MCP client config. The OAuth variant prompts you to authorize on first connect, so no token sits in your config file.
OAuth (recommended):
{"mcpServers": {"mamba-labs-icp-scorer": {"url": "https://mcp.apify.com?tools=mambalabs/icp-fit-scorer"}}}
Bearer token:
{"mcpServers": {"mamba-labs-icp-scorer": {"url": "https://mcp.apify.com?tools=mambalabs/icp-fit-scorer","headers": {"Authorization": "Bearer YOUR_APIFY_TOKEN"}}}}
Setup: Full Mamba Labs GTM Suite
Load all 6 Mamba Labs GTM actors as tools in a single MCP server entry.
OAuth:
{"mcpServers": {"mamba-labs-gtm-suite": {"url": "https://mcp.apify.com?tools=mambalabs/gtm-hiring-signal-scraper,mambalabs/gtm-tech-stack-signal-scraper,mambalabs/gtm-signals-aggregator,mambalabs/job-board-keyword-signal-scanner,mambalabs/domain-to-linkedin-url-resolver,mambalabs/icp-fit-scorer"}}}
Bearer token:
{"mcpServers": {"mamba-labs-gtm-suite": {"url": "https://mcp.apify.com?tools=mambalabs/gtm-hiring-signal-scraper,mambalabs/gtm-tech-stack-signal-scraper,mambalabs/gtm-signals-aggregator,mambalabs/job-board-keyword-signal-scanner,mambalabs/domain-to-linkedin-url-resolver,mambalabs/icp-fit-scorer","headers": {"Authorization": "Bearer YOUR_APIFY_TOKEN"}}}}
Setup: Local server (for development and testing)
npx @apify/actors-mcp-server --tools mambalabs/icp-fit-scorer
Full suite:
npx @apify/actors-mcp-server --tools mambalabs/gtm-hiring-signal-scraper,mambalabs/gtm-tech-stack-signal-scraper,mambalabs/gtm-signals-aggregator,mambalabs/job-board-keyword-signal-scanner,mambalabs/domain-to-linkedin-url-resolver,mambalabs/icp-fit-scorer
What the output looks like
Flat JSON, one row per scored company, under 2KB. The most useful fields:
icp_score: overall fit score from 0 to 100.icp_tier: A (80-100), B (60-79), C (40-59), or D (0-39).lead_tag: priority (A), nurture (B/C), or disqualify (D). Decision band ready for filters.score_hiring,score_tech_stack,score_headcount,score_funding,score_industry: per-criterion point breakdown.signals_matchedandsignals_missing: comma-separated lists of which signals scored and which did not.config_source: "explicit" when a JSON config was provided, "llm_generated" when generated from an ICP description.score_explanation: human-readable summary of the scoring math. Present wheninclude_explanationis true or in LLM mode.
Billing
MCP runs use the same pay-per-event pricing as direct API or Console runs. Each successful result costs $0.05.
Notes
The default mode is deterministic (no LLM call, no extra cost). Setting icp_description plus an llm_api_key switches to LLM mode, which adds 2 to 5 seconds per run and incurs an additional per-run API cost from your own LLM provider. For MCP usage, deterministic mode with a scoring_config is recommended unless natural-language summaries in the output are specifically needed.
Part of the Mamba Labs GTM Suite
This actor is part of the Mamba Labs GTM Suite. See all 6 actors at https://apify.com/mambalabs
Built by Mamba Labs.