# Hiring Signal Detector - AI Buying Trigger from Careers (`fetchcraft/hiring-signal-detector`) Actor

Score company careers pages by buying-signal strength: team scale-up vs replacement hire vs new function. Returns open role count, ATS provider, top hiring titles, and AI-generated outreach angle. Bring your own LLM key. $0.01 detector, $0.03 with AI angle.

- **URL**: https://apify.com/fetchcraft/hiring-signal-detector.md
- **Developed by:** [Emily Ward](https://apify.com/fetchcraft) (community)
- **Categories:** Lead generation, AI, Jobs
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 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: which ATS they use, how many open roles, top role titles, departments hiring, tech stack signals from job descriptions, and a hiring velocity rating.
>
> For SDRs targeting expanding companies (active hiring is the cleanest budget signal in B2B), recruiters finding clients, and VCs tracking portfolio growth.

### 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": "If you sell infra/dev tools, the heavy hiring in distributed systems + AI signals near-term need for observability and embedding/vector infrastructure.",
    "urgency_signal": "rapid",
    "estimated_headcount": "~700",
    "reasoning": "399 open roles with 60% engineering and 15% sales suggests product-first growth phase, likely Series C+."
  }
}
````

### Modes

#### Preview (free)

1 URL only, not charged. Output goes to dataset for inspection. No event fired.

#### Regex (A$0.15 per result)

- Discovers careers page via 12 common paths + 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 or generic selectors
- Extracts and filters role titles (filters out language nav, generic links, region anchors)
- Buckets titles into departments (Engineering, Sales, Marketing, Product, Customer Success, Operations, Design, Data)
- Computes hiring velocity (very\_high, high, moderate, low, minimal) and growth signal (broad\_scale\_up, product\_engineering\_build, go\_to\_market\_expansion, steady\_growth, targeted\_hiring, no\_signal)

**Honest limitations:**

- Role count is reliable across all ATS-embedded sites and most SSR sites
- Title extraction is reliable for Greenhouse / Lever / Workable embedded pages; less reliable for SPA pages (Notion, Stripe, Atlassian load roles client-side after hydration, so initial HTML may not expose titles)
- ATS detection misses companies using fully custom ATS (Stripe, Atlassian have internal systems)
- For SPA-heavy sites where titles aren't in initial HTML, the role count still works; use AI mode for richer inference

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

- Everything in regex mode, plus:
- Sends cleaned careers page content to Claude Sonnet 4.6 with a senior B2B sales intelligence prompt
- Returns: company stage, growth thesis, tech stack signals (with verbatim evidence quotes), decision-maker signals, best sales pitch angle, urgency signal, estimated headcount, reasoning

AI mode is the right pick when you're feeding the output directly into outreach (you want the pitch angle, not just the data).

### Inputs

| Field | Type | Default | Description |
| --- | --- | --- | --- |
| urls | array of strings | required | Company URLs (homepage; the actor auto-discovers /careers) |
| mode | string | `regex` | `preview`, `regex`, or `ai` |
| min\_open\_roles\_filter | integer | 0 | Skip companies with fewer open roles than this (still charged; set to 5+ to focus on actively expanding companies) |
| max\_concurrency | integer | 5 | Parallel URLs (1 to 20) |

### Use cases

- **B2B SDR prospecting:** Hiring is the cleanest budget signal in B2B. A company with 20+ open engineering roles needs dev tools, observability, security, infra. A company with 10+ sales roles needs CRM, sales engagement, enablement. Use this to build a "warm prospect" list every Monday from your TAM.
- **Recruiting agencies:** Find companies hiring in your specialty. Pitch a retained search.
- **VC / PE portfolio monitoring:** Quarterly snapshot of which portfolio companies are scaling fastest by net new headcount.
- **Sales intelligence platforms:** White-label or supplement existing tools.
- **Pre-sales discovery:** Before a discovery call, run this to walk in knowing their growth stage and tech stack.
- **Competitive intelligence:** Track what your competitors are hiring for. Their hiring tells you their roadmap.

### Cost economics

| You run | Regex mode | AI mode |
| --- | --- | --- |
| 10 URLs | ~A$1.50 | ~A$4.00 |
| 100 URLs | ~A$15.00 | ~A$40.00 |
| 1,000 URLs | ~A$150.00 | ~A$400.00 |

The Actor itself doesn't charge a subscription. You pay only for results you generate, billed to your Apify account.

### What this Actor does NOT do

- Scrape individual job descriptions (it counts and extracts titles, but doesn't fetch the full JD for every role)
- Detect hiring on LinkedIn-only postings (only public careers pages)
- Replace LinkedIn Sales Navigator's intent data (this is signal, not intent)
- Track salary information (most public careers pages don't expose this)
- Determine hiring trends over time (single snapshot per run; for trends, re-run weekly and diff)

### What to do with the output

For sales prospecting:

1. Run on your TAM weekly (50-200 URLs)
2. Filter: `min_open_roles_filter=10` to focus on actively expanding companies
3. Use `top_department` to route to the right SDR pod (Engineering hiring → infra/dev-tool reps; Sales hiring → CRM/sales-tool reps)
4. Use AI mode's `best_sales_pitch_angle` as your opener seed

Pair with the [AI Sales Personalizer](https://apify.com/fetchcraft/ai-sales-personalizer) for end-to-end: this actor identifies WHO is hot, Personalizer writes the opener.

### About the maintainer

Built by [Emily Ward](https://cancelcosts.com), Admitted Lawyer (NSW) turned AI builder, Founder of Cancel Costs and OmniApp.ai.

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 - AI Buying Trigger from Careers",
        "description": "Score company careers pages by buying-signal strength: team scale-up vs replacement hire vs new function. Returns open role count, ATS provider, top hiring titles, and AI-generated outreach angle. Bring your own LLM key. $0.01 detector, $0.03 with AI angle.",
        "version": "0.1",
        "x-build-id": "lnsaBVIA3m5MhS0el"
    },
    "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
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
