# SaaS Spend Scanner (Tools + Cost Estimates + Tech Stack) (`fetchcraft/saas-spend-scanner`) Actor

Drop in company URLs. Get back every SaaS, analytics, marketing, chat, CRM, and ops tool detectable from each site, with a monthly cost estimate per tool plus a per-company total. Two modes: regex (fast, cheap) or AI-enhanced (deeper). Pay per result.

- **URL**: https://apify.com/fetchcraft/saas-spend-scanner.md
- **Developed by:** [Emily Ward](https://apify.com/fetchcraft) (community)
- **Categories:** Lead generation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, NaN bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per event

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp.md).

If your project is in a different language, use the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).


# README

## SaaS Spend Scanner

> Drop in a list of company URLs. Get back every SaaS, analytics, marketing, chat, CRM, and ops tool detectable from each site, with a monthly cost estimate per tool and a total per company.
>
> Know what tools your prospects are paying for before you reach out. Surface displacement opportunities. Identify competitive risk.

### What this solves

"They're on a competitor" is information you want BEFORE the sales call, not during it. And "they're already paying A$3,500/month in tool costs we could consolidate" is a much better opener than a cold pitch.

This actor scans company websites for vendor signals, estimates their SaaS spend by category, and identifies which tools they're using. In AI mode, it also surfaces hidden vendors from non-obvious signals (privacy pages, preconnect hints, hiring JDs).

### What you get per URL

```json
{
  "input_url": "https://stripe.com",
  "company_name": "Stripe",
  "mode": "ai",
  "currency": "AUD",
  "tools": [
    { "name": "Vercel", "category": "Hosting / Infra", "estimated_monthly": 400, "currency": "AUD" }
  ],
  "tools_detected_count": 8,
  "estimated_monthly_aud": 4200,
  "by_category": {
    "Hosting / Infra": { "tools": [...], "subtotal": 400 },
    "Customer Data": { "tools": [...], "subtotal": 1200 }
  },
  "ai_insights": {
    "company_size_estimate": "1000+",
    "industry": "Payments / Financial Infrastructure",
    "additional_tools_detected": [
      { "name": "Greenhouse", "category": "Hiring", "evidence_quote": "open roles powered by greenhouse", "estimated_monthly_aud": 800, "confidence": "high" }
    ],
    "estimated_additional_monthly_aud": 2000,
    "top_3_actions": [
      "Audit Segment workspace utilization vs cost",
      "Negotiate annual on Salesforce given footprint indicators"
    ]
  }
}
````

### Modes

#### Preview (free)

1 URL only, no charge. For testing output format before a paid batch.

#### Regex ($0.10 per result, recommended for bulk)

- Fetches homepage HTML
- Pattern-matches against 87+ signatures across 16 categories
- Categories: analytics (GA, Mixpanel, Segment, Hotjar, Heap, PostHog), marketing pixels (Facebook, LinkedIn, TikTok), support chat (Intercom, Drift, Zendesk, Crisp), CRMs (HubSpot, Marketo, Pardot), forms/booking (Typeform, Calendly, Cal.com), CMSs (WordPress, Webflow, Shopify, Squarespace), hosting (Next.js, Nuxt, Vercel, Netlify), compliance (OneTrust, Cookiebot), error monitoring (Sentry), observability (Datadog, New Relic), CDN/security (Cloudflare, Fastly), video (Wistia, Loom, Vimeo), and more
- Also catches preconnect and dns-prefetch hints, which reveal vendor relationships even when the actual tracker scripts load client-side

**Honest limitation:** Regex sees initial HTML only. SPA-heavy sites (Stripe, Notion, Atlassian) load analytics client-side after React hydration. For those sites, use AI mode for deeper coverage.

#### AI-enhanced ($0.50 per result, for serious audits)

Runs the regex pass, then Claude AI:

- Reads the full page source including comments, inline scripts, and non-obvious vendor references
- Checks the privacy policy, terms page, and cookie consent for vendor disclosures (companies are legally required to list data processors there)
- Infers additional vendors from job posting technology requirements
- Generates cost estimates factoring in company size

AI mode typically surfaces 3 to 8 additional tools the regex pass misses, especially on enterprise sites.

### Input format

```json
{
  "urls": ["https://acme.com", "https://competitor.com"],
  "mode": "regex"
}
```

- `urls`: array of company URLs (homepage preferred, but any company domain URL works)
- `mode`: `"preview"` | `"regex"` | `"ai"` (default: `"regex"`)

### Who uses this

- **SDRs and AEs** who want to mention a prospect's current tools in an opener ("I noticed you're running Intercom + HubSpot...")
- **Sales engineers** doing pre-call research on a prospect's tech stack
- **Competitive intelligence** teams monitoring which tools customers of a competitor are using
- **Cost consultants and VCs** estimating SaaS spend across a portfolio
- **Agencies** auditing what their prospective clients are paying for before quoting

### FAQ

**Q: How accurate are the cost estimates?**
Estimates are based on standard published pricing for a company of the detected size. They are indicative, not exact. The estimate is useful for "they're spending A$3,000-5,000/month in this category" conversations, not for line-item billing audits.

**Q: What if a tool isn't in your detection list?**
Submit a GitHub issue or email emily@cancelcosts.com with the tool name and vendor signals. New tools are typically added within 48 hours.

**Q: Can I get raw signal data (the matched patterns)?**
The `_meta` field includes the provider and latency. For raw matched signals, contact the actor owner for a custom output format.

**Q: How many URLs can I run at once?**
Up to 10,000. Regex mode at 200 URLs costs approximately $20 AUD.

### The B2B Sales Intelligence Suite

This actor is part of a 4-actor suite by Emily Ward that turns a raw TAM list into a ranked, personalised outreach queue:

1. **[Hiring Signal Detector](https://apify.com/fetchcraft/hiring-signal-detector)**: who's expanding?
2. **[Funding Round Tracker](https://apify.com/fetchcraft/funding-round-tracker)**: who has fresh capital?
3. **[SaaS Spend Scanner](https://apify.com/fetchcraft/saas-spend-scanner)** (you are here): what do they pay for?
4. **[AI Sales Personalizer](https://apify.com/fetchcraft/ai-sales-personalizer)**: write the opener.

Used together, they 3x outbound conversion vs working from a raw TAM list. What used to take a 5-person SDR team a week takes 1 person 2 hours and ~$95 AUD in Apify credits.

***

Tags: `saas` `spend` `tech-stack` `competitive-intelligence` `b2b` `sales-intelligence` `vendor-detection` `lead-enrichment`

Made by Emily Ward, Founder of Cancel Costs. Questions: emily@cancelcosts.com

# Actor input Schema

## `urls` (type: `array`):

List of company homepage URLs. One result per URL.

## `mode` (type: `string`):

regex: fast, 70+ patterns, ~A$0.10 per URL. ai: regex + Claude analysis catches non-obvious tools (hiring platforms, support email domains, compliance vendors, etc.), ~A$0.50 per URL. preview: first URL only, not charged, for testing.

## `currency` (type: `string`):

Cost estimates are based on typical SMB pricing in this currency.

## `include_free_tools` (type: `boolean`):

If true, free tools like Google Analytics, Cloudflare, PostHog (free tier) appear in the list with A$0 cost. If false, only paid tools are shown.

## `max_concurrency` (type: `integer`):

How many URLs to process in parallel.

## Actor input object example

```json
{
  "urls": [
    "https://www.stripe.com",
    "https://www.notion.so",
    "https://www.atlassian.com"
  ],
  "mode": "regex",
  "currency": "AUD",
  "include_free_tools": true,
  "max_concurrency": 5
}
```

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "urls": [
        "https://www.stripe.com",
        "https://www.notion.so",
        "https://www.atlassian.com"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("fetchcraft/saas-spend-scanner").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = { "urls": [
        "https://www.stripe.com",
        "https://www.notion.so",
        "https://www.atlassian.com",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("fetchcraft/saas-spend-scanner").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "urls": [
    "https://www.stripe.com",
    "https://www.notion.so",
    "https://www.atlassian.com"
  ]
}' |
apify call fetchcraft/saas-spend-scanner --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=fetchcraft/saas-spend-scanner",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "SaaS Spend Scanner (Tools + Cost Estimates + Tech Stack)",
        "description": "Drop in company URLs. Get back every SaaS, analytics, marketing, chat, CRM, and ops tool detectable from each site, with a monthly cost estimate per tool plus a per-company total. Two modes: regex (fast, cheap) or AI-enhanced (deeper). Pay per result.",
        "version": "0.1",
        "x-build-id": "FS6OEd4FjyfYZosNt"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/fetchcraft~saas-spend-scanner/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-fetchcraft-saas-spend-scanner",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/fetchcraft~saas-spend-scanner/runs": {
            "post": {
                "operationId": "runs-sync-fetchcraft-saas-spend-scanner",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/fetchcraft~saas-spend-scanner/run-sync": {
            "post": {
                "operationId": "run-sync-fetchcraft-saas-spend-scanner",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "required": [
                    "urls"
                ],
                "properties": {
                    "urls": {
                        "title": "Company URLs",
                        "type": "array",
                        "description": "List of company homepage URLs. One result per URL.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "mode": {
                        "title": "Scan mode",
                        "enum": [
                            "preview",
                            "regex",
                            "ai"
                        ],
                        "type": "string",
                        "description": "regex: fast, 70+ patterns, ~A$0.10 per URL. ai: regex + Claude analysis catches non-obvious tools (hiring platforms, support email domains, compliance vendors, etc.), ~A$0.50 per URL. preview: first URL only, not charged, for testing.",
                        "default": "regex"
                    },
                    "currency": {
                        "title": "Currency for cost estimates",
                        "enum": [
                            "AUD",
                            "USD",
                            "EUR",
                            "GBP"
                        ],
                        "type": "string",
                        "description": "Cost estimates are based on typical SMB pricing in this currency.",
                        "default": "AUD"
                    },
                    "include_free_tools": {
                        "title": "Include free tools in detected list",
                        "type": "boolean",
                        "description": "If true, free tools like Google Analytics, Cloudflare, PostHog (free tier) appear in the list with A$0 cost. If false, only paid tools are shown.",
                        "default": true
                    },
                    "max_concurrency": {
                        "title": "Max parallel requests",
                        "minimum": 1,
                        "maximum": 20,
                        "type": "integer",
                        "description": "How many URLs to process in parallel.",
                        "default": 5
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
