# Hiring Signal Detector (ATS, Velocity, Tech Stack) (`fetchcraft/hiring-signal-detector`) Actor

Drop in company URLs. Get back ATS in use (Greenhouse, Lever, Workable, Ashby, etc), open role count, top role titles, departments hiring, tech stack signals from job descriptions, and a hiring velocity rating. For SDRs, recruiters, and VCs tracking growth.

- **URL**: https://apify.com/fetchcraft/hiring-signal-detector.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

## Hiring Signal Detector

> Drop in a list of company URLs. Get back: ATS provider, open role count, hiring departments, tech stack signals from job descriptions, and a hiring velocity rating (very_high / high / moderate / low / minimal).
>
> Active hiring is the #1 budget signal in B2B sales. Know which companies are scaling before your competitors do.

### What this solves

Most SDR teams waste 70% of their time on the wrong accounts. Companies that aren't actively hiring have already frozen headcount, which means frozen budgets. Companies that are hiring aggressively are spending money and need tools to support their growth.

This actor tells you, per URL in your TAM list, exactly how aggressively a company is hiring, what departments are expanding, what tools are in their tech stack, and who the budget decision makers are.

### What you get per URL

```json
{
  "input_url": "https://www.notion.so",
  "company_name": "Notion",
  "mode": "ai",
  "careers_url": "https://www.notion.so/careers",
  "ats_provider": "Ashby",
  "open_roles_count": 399,
  "top_titles": ["Staff Backend Engineer, Search", "Senior Product Manager, AI"],
  "departments_hiring": { "Engineering": 11, "Sales": 4, "Product": 3 },
  "top_department": "Engineering",
  "hiring_velocity": "very_high",
  "growth_signal": "product_engineering_build",
  "ai_insights": {
    "company_stage": "growth",
    "growth_thesis": "Investing heavily in AI product surfaces and enterprise-scale infra.",
    "tech_stack_signals": [
      { "tool": "TypeScript", "evidence_quote": "TypeScript across the stack", "confidence": "high" },
      { "tool": "Snowflake", "evidence_quote": "Build production data pipelines in Snowflake", "confidence": "high" }
    ],
    "decision_maker_signals": [
      { "role": "VP Engineering", "buying_authority_for": "developer tooling, security, observability" },
      { "role": "Head of Sales Ops", "buying_authority_for": "CRM, sales engagement, BI tools" }
    ],
    "best_sales_pitch_angle": "Heavy hiring in distributed systems + AI signals near-term need for observability and embedding infrastructure.",
    "urgency_signal": "rapid",
    "estimated_headcount": "~700"
  }
}
````

### Modes

#### Preview (free)

1 URL only, no charge. Use to test output format and verify actor runs correctly on your input format.

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

- Discovers careers page via 12 common paths and linked-anchor detection from homepage
- Detects ATS from 15 providers (Greenhouse, Lever, Workable, Ashby, SmartRecruiters, Recruitee, Personio, BambooHR, JazzHR, Teamtailor, Pinpoint, Rippling, Workday, iCIMS, Taleo)
- Counts open roles using ATS-specific and generic selectors
- Extracts and filters role titles (filters out navigation links and region anchors)
- Buckets titles into departments (Engineering, Sales, Marketing, Product, Customer Success, Operations, Design, Data)
- Computes hiring velocity and growth signal from role count and department mix

**Honest limitation:** Role count is reliable across all ATS-embedded sites and most SSR sites. Title extraction is less reliable for SPA-heavy sites (Notion, Stripe, Atlassian) that load roles client-side after React hydration. For those sites, role count still works; use AI mode for richer inference.

#### AI-enhanced ($0.40 per result)

Runs the regex pass first, then Claude AI reads the careers page and up to 3 linked JDs to extract:

- Tech stack signals with evidence quotes
- Decision maker titles and buying authority
- Growth thesis and stage assessment
- Best sales pitch angle

Use AI mode for high-priority accounts where the extra context is worth the cost.

### Input format

```json
{
  "urls": ["https://stripe.com", "https://notion.so"],
  "mode": "regex"
}
```

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

### Who uses this

- **SDRs and AEs** targeting expanding companies from a TAM list
- **Recruiters** finding high-growth companies that need their services
- **VCs** tracking portfolio headcount velocity
- **Competitive intelligence** teams monitoring who a competitor is hiring

### FAQ

**Q: What if a company uses a custom ATS not on your list?**
The actor still counts roles from generic selectors (numbered list items, job-card elements). The ATS field returns `"custom_or_unknown"`. Open role count is still reliable.

**Q: Does it work for companies with no careers page?**
The actor returns `careers_url: null` and `open_roles_count: 0`. It still returns all other data including mode, input URL, and company name.

**Q: Can I run 500 URLs at once?**
Yes. The actor handles batches via Apify's standard input schema. Input up to 10,000 URLs. Regex mode at 500 URLs costs approximately $50 AUD.

**Q: How often is the data fresh?**
Each run fetches live data. There is no cache. Roles are live at time of run.

### 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)** (you are here): 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)**: 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: `hiring` `recruiting` `sales-intelligence` `ats` `b2b` `lead-generation` `jobs` `signal-detection`

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

# Actor input Schema

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

List of company URLs. The actor auto-discovers their careers page from common paths.

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

regex: ATS + role count + department detection from HTML, ~A$0.15 per result. ai: regex + Claude analysis infers growth signal, decision-maker signals, tech stack, ~A$0.40 per result. preview: 1 URL only, not charged.

## `min_open_roles_filter` (type: `integer`):

Skip results where open roles count is below this. Set to 0 to include all. Set to 5+ to filter for companies actively expanding.

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

How many URLs to process in parallel.

## Actor input object example

```json
{
  "urls": [
    "https://www.atlassian.com",
    "https://www.notion.so",
    "https://www.gymshark.com"
  ],
  "mode": "regex",
  "min_open_roles_filter": 0,
  "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.atlassian.com",
        "https://www.notion.so",
        "https://www.gymshark.com"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("fetchcraft/hiring-signal-detector").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.atlassian.com",
        "https://www.notion.so",
        "https://www.gymshark.com",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("fetchcraft/hiring-signal-detector").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.atlassian.com",
    "https://www.notion.so",
    "https://www.gymshark.com"
  ]
}' |
apify call fetchcraft/hiring-signal-detector --silent --output-dataset

```

## MCP server setup

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

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Hiring Signal Detector (ATS, Velocity, Tech Stack)",
        "description": "Drop in company URLs. Get back ATS in use (Greenhouse, Lever, Workable, Ashby, etc), open role count, top role titles, departments hiring, tech stack signals from job descriptions, and a hiring velocity rating. For SDRs, recruiters, and VCs tracking growth.",
        "version": "0.1",
        "x-build-id": "sJUbq8mIkAedidZND"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/fetchcraft~hiring-signal-detector/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-fetchcraft-hiring-signal-detector",
                "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~hiring-signal-detector/runs": {
            "post": {
                "operationId": "runs-sync-fetchcraft-hiring-signal-detector",
                "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~hiring-signal-detector/run-sync": {
            "post": {
                "operationId": "run-sync-fetchcraft-hiring-signal-detector",
                "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 URLs. The actor auto-discovers their careers page from common paths.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "mode": {
                        "title": "Mode",
                        "enum": [
                            "preview",
                            "regex",
                            "ai"
                        ],
                        "type": "string",
                        "description": "regex: ATS + role count + department detection from HTML, ~A$0.15 per result. ai: regex + Claude analysis infers growth signal, decision-maker signals, tech stack, ~A$0.40 per result. preview: 1 URL only, not charged.",
                        "default": "regex"
                    },
                    "min_open_roles_filter": {
                        "title": "Minimum open roles filter",
                        "minimum": 0,
                        "maximum": 100,
                        "type": "integer",
                        "description": "Skip results where open roles count is below this. Set to 0 to include all. Set to 5+ to filter for companies actively expanding.",
                        "default": 0
                    },
                    "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
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
