# Hiring Intent & Stack Radar (`axiom-labs/hiring-intent-stack-radar`) Actor

Turn fresh public hiring activity into recruiter-ready company opportunities. Finds open roles, tech stacks, and generic contacts without LinkedIn login.

- **URL**: https://apify.com/axiom-labs/hiring-intent-stack-radar.md
- **Developed by:** [Samuel Fernandes](https://apify.com/axiom-labs) (community)
- **Categories:** Lead generation
- **Stats:** 1 total users, 0 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $20.00 / 1,000 qualified hiring companies

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/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — 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 Intent & Stack Radar

### Find the next client requisition before it reaches your inbox

**Hiring Intent & Stack Radar** turns fresh public hiring activity into recruiter-ready company opportunities. It discovers matching roles from public ATS and career pages, groups multiple openings by employer, cross-checks the employer’s official website, and returns the evidence a recruiting agency needs to decide **who to contact now and why**.

A typical result looks like this:

> “This company opened three matching engineering roles this week, is publicly hiring for the stack your agency specializes in, and has a verified official careers/contact route.”

The Actor does **not** scrape candidate profiles, personal LinkedIn pages, private recruiter data, or personal email addresses. It finds public employer-side hiring signals and makes them actionable.

### Why recruiting agencies use it

Recruiting agencies win when they reach a potential client while the hiring need is fresh. Searching one job board at a time misses roles posted on company career sites and ATS pages, while manually grouping roles by employer and researching each company’s technology stack consumes hours that could be spent on business development.

Hiring Intent & Stack Radar compresses that workflow into a structured dataset. Instead of downloading a flat list of job postings, you receive one normalized record per employer, including open-role clusters, posting recency, technology evidence, source URLs, a transparent intent score, and a generic company contact route when publicly available.

This is particularly useful for agencies focused on **AI, data, cloud, DevOps, cybersecurity, platform engineering, software engineering, and other specialized technical hiring**.

### The no-login advantage

This Actor is designed around public, structured employer-side sources:

- **No LinkedIn login or cookies.** The default workflow does not access personal LinkedIn profiles or authenticated pages.
- **Direct ATS parsing.** When available, it queries public structured endpoints for Greenhouse, Lever, Ashby, and SmartRecruiters instead of relying on fragile browser selectors.
- **Lower blocking surface.** Public ATS endpoints and official career pages are generally a more maintainable source layer than authenticated social pages. The Actor can use Apify Proxy rotation when enabled, but no scraper can guarantee that every website will remain unblocked forever.
- **Business-safe contact framing.** It returns generic public routes such as a company contact page, careers page, talent page, or clearly generic business email. Personal emails and personal social profiles are excluded.

> The product discovers **public hiring signals that may be unadvertised to your current sourcing workflow**. It does not claim access to private or confidential requisitions.

### What the Actor does

The Actor supports two discovery modes:

| Mode | Best for | How it works |
|---|---|---|
| **Keyword search** | Finding new companies by role and location | Builds targeted public search queries for common ATS domains such as Greenhouse, Lever, Ashby, SmartRecruiters, and Workable, then processes only the discovered candidate URLs. |
| **Target URLs** | Scheduled monitoring of known companies | Accepts public ATS boards, career pages, job URLs, or company domains and extracts current matching roles directly. |
| **Both** | Prospecting plus account monitoring | Combines search discovery with a user-supplied monitoring list. |

For supported ATS platforms, the Actor uses API-first extraction. When a structured endpoint is unavailable, it falls back to JSON-LD and Cheerio parsing of the supplied public page. The Actor does not perform blind recursive crawling.

### Quick start

A minimal recruiter-oriented input looks like this:

```json
{
  "discoveryMode": "both",
  "roleKeywords": ["data engineer", "AI engineer", "Kubernetes"],
  "locations": ["United States", "United Kingdom"],
  "postedWithinDays": 7,
  "technologyKeywords": ["AWS", "Snowflake", "Kubernetes"],
  "minimumOpenRolesPerCompany": 1,
  "maxCompanies": 100
}
```

For recurring account monitoring, provide company domains or public ATS URLs:

```json
{
  "discoveryMode": "target_urls",
  "roleKeywords": ["software engineer"],
  "seedCompanyDomains": ["example.com", "example.ai"],
  "seedCareerUrls": [
    "https://boards.greenhouse.io/example",
    "https://jobs.ashbyhq.com/example-ai"
  ],
  "postedWithinDays": 14,
  "maxCompanies": 50
}
```

### Input fields

The full recruiter-friendly schema is included in `INPUT_SCHEMA.json`. The most important fields are:

| Field | Description | Default |
|---|---|---|
| `discoveryMode` | `keyword_search`, `target_urls`, or `both` | `both` |
| `roleKeywords` | Job-title phrases to match against the role title | `data engineer` |
| `locations` | Optional location filters | Empty |
| `workMode` | `remote`, `hybrid`, `onsite`, or `any` | `any` |
| `postedWithinDays` | Freshness window for posted roles; `0` disables the filter | `7` |
| `targetSources` | ATS families to accept, or `auto` | `auto` |
| `seedCompanyDomains` | Official employer domains for monitoring | Empty |
| `seedCareerUrls` | Public ATS or career URLs for monitoring | Empty |
| `technologyKeywords` | Technologies to match and evidence | Empty |
| `technologyMatchMode` | Require `any` or `all` requested technologies | `any` |
| `minimumOpenRolesPerCompany` | Minimum matching roles to qualify an employer | `1` |
| `includeTechnologyEvidence` | Include evidence URLs and snippets | `true` |
| `includeContactRoute` | Include generic public company routes | `true` |
| `maxCompanies` | Maximum deduplicated employer records | `500` |
| `proxyMode` | `auto`, `datacenter`, or `none` | `auto` |

`roleKeywords` match **job titles only**. This prevents an unrelated posting such as “Technical Recruiter” from qualifying for an `engineer` filter merely because its description discusses engineering hiring.

### Output: one qualified company record per result

The primary output is written to the **default dataset** as one record per deduplicated employer. A result is qualified only when the Actor confirms a matching active role, resolves a canonical company domain, and cross-references at least two public source families.

#### Shortened JSON preview

```json
{
  "schemaVersion": "1.0.0",
  "recordType": "hiring_intent_company",
  "retrievedAt": "2026-08-21T05:57:59.000Z",
  "company": {
    "name": "Linear",
    "canonicalDomain": "linear.app",
    "companyUrls": {
      "homepage": "https://linear.app/",
      "contact": "https://linear.app/contact"
    }
  },
  "hiringIntent": {
    "intentScore": 80,
    "intentTier": "high",
    "openRoleCount": 3,
    "freshestPostedAt": "2026-08-11T00:36:47.459Z",
    "roleClusters": [
      {
        "cluster": "data_engineering",
        "roleCount": 1,
        "seniorityBands": [],
        "locations": ["Remote"]
      }
    ],
    "scoreReasons": [
      "3 matching roles passed the requested filters",
      "No requested technology filter was applied",
      "Job source and official company evidence were cross-referenced"
    ]
  },
  "roles": [
    {
      "title": "Analytics Engineer",
      "normalizedTitle": "analytics_engineer",
      "postedAt": "2026-08-11T00:36:47.459Z",
      "location": {"city": "Remote", "countryCode": null},
      "source": {
        "sourceType": "ashby",
        "url": "https://jobs.ashbyhq.com/linear/..."
      }
    }
  ],
  "technologySignals": [
    {
      "technology": "Databricks",
      "category": "data",
      "confidence": 0.9,
      "evidenceType": "job_text",
      "evidenceUrl": "https://jobs.ashbyhq.com/linear/..."
    }
  ],
  "contactability": {
    "contactPageUrl": "https://linear.app/contact",
    "publicEmail": null,
    "personalContactCollected": false
  },
  "quality": {
    "sourceCount": 3,
    "fieldCompleteness": 1,
    "isQualified": true,
    "warnings": []
  }
}
```

Every role and enrichment signal includes source provenance and retrieval timestamps. Technology signals are evidence-backed; ambiguous names such as **Go**, **Rust**, **Angular**, and **Next.js** require technical context and are filtered out when they appear in generic marketing copy, URLs, CSS, or style declarations.

### Transparent Pay-Per-Event pricing

The Actor uses explicit custom PPE events. The base event is charged first with `Actor.charge()`. Only after the charge succeeds does the Actor write the record to the default dataset, so your downloaded results are not hidden in a named dataset.

| Event | Suggested price | What qualifies |
|---|---:|---|
| `qualified_hiring_company` | **$0.020 / employer** | Matching active role, canonical domain, at least two public source families, and requested filters satisfied. |
| `technology_signal_evidence` | **$0.008 / employer** | At least one technology signal with a source URL and evidence type. |
| `public_contact_route` | **$0.012 / employer** | Generic public contact, careers, talent route, or generic business email. |
| `firmographic_enrichment` | **$0.004 / employer** | Public industry, headquarters, location, or company-size evidence. |
| Inconclusive or duplicate record | **$0.000** | Not billed as a qualified employer result. |

A typical qualified result with all three optional enrichments costs:

```text
$0.020 base employer record
+ $0.008 technology evidence
+ $0.012 generic contact route
+ $0.004 firmographic enrichment
= $0.044 maximum PPE for that record
```

You can disable optional enrichment fields to reduce cost. The final event prices must be configured in the Actor’s **Monetization** settings in Apify Console. Apify’s PPE model calculates publisher profit as 80% of event revenue minus platform usage costs; monitor actual compute and proxy costs after the first production runs.[1]

### Privacy and responsible use

Hiring Intent & Stack Radar processes public employer-side information only. It does not collect candidate profiles, personal LinkedIn pages, private recruiter information, personal emails, or sensitive candidate data. Generic business contact routes are returned for business outreach and should be used in accordance with applicable privacy, marketing, and anti-spam laws.

The Actor provides source URLs and retrieval timestamps so users can verify the public evidence themselves. A job posting is a hiring signal, not proof that a company will use an external recruiting agency or that a role remains open after retrieval.

### Performance and reliability

The Actor uses API-first public ATS adapters, Cheerio/JSON-LD fallback parsing, request retries, bounded concurrency, Crawlee session management, and optional Apify Proxy rotation. Missing selectors or malformed JSON-LD do not crash the run; the Actor records diagnostics and continues with other valid inputs.

For scheduled monitoring, use `target_urls` with a bounded list of public company domains or ATS boards. For broad discovery, use `keyword_search` with focused role and location filters rather than large undirected queries.

### Files included

| File | Purpose |
|---|---|
| `main.js` | Node.js/Crawlee Actor implementation |
| `INPUT_SCHEMA.json` | Apify input form and validation schema |
| `package.json` | Runtime dependencies and start command |
| `README.md` | Store detail page and user documentation |

### Support and troubleshooting

If a source returns no jobs, confirm that the ATS URL is public and that the company slug is correct. Reduce `maxConcurrency` or use `proxyMode: auto` when a public source rate-limits requests. For a reproducible support report, include the Actor run ID, input JSON, source URL, and the diagnostic dataset output. Do not include cookies, private credentials, or personal candidate information.

### References

[1]: https://docs.apify.com/actors/publishing/monetize/pay-per-event "Apify — Pay-per-event pricing model"

[2]: https://docs.apify.com/actors/development/deployment "Apify — Actor deployment"

[3]: https://docs.apify.com/actors/publishing/publish "Apify — Publish your Actor"

# Actor input Schema

## `discoveryMode` (type: `string`):

Choose keyword search, direct company/ATS monitoring, or both. Direct monitoring is best for recurring runs.

## `roleKeywords` (type: `array`):

Enter job titles or skill phrases such as AI engineer, data engineer, Kubernetes, cybersecurity, or Snowflake.

## `locations` (type: `array`):

Optional cities, regions, or countries. Leave empty to search all locations.

## `workMode` (type: `string`):

Filter by remote, hybrid, onsite, or any work arrangement.

## `seniority` (type: `array`):

Optional seniority filters.

## `employmentTypes` (type: `array`):

Optional employment-type filters.

## `postedWithinDays` (type: `integer`):

Return jobs posted or first observed within this window when a source date is available. Use 0 to disable the date filter.

## `targetSources` (type: `array`):

Choose public structured sources to use. Auto detects the source from each URL and enables all supported adapters.

## `seedCompanyDomains` (type: `array`):

Optional official company domains, for example example.com. The Actor discovers the company careers page and public contact route without crawling unrelated pages.

## `seedCareerUrls` (type: `array`):

Optional direct public career-page, ATS board, or job-posting URLs. Use this for scheduled monitoring of known companies.

## `searchQueries` (type: `array`):

Optional search-engine queries. If empty, the Actor builds targeted ATS queries from role keywords and locations. Use public search discovery only; the Actor does not crawl search-result pages recursively.

## `searchProviders` (type: `array`):

Search providers used only in keyword-search mode. The Actor falls back when a provider is unavailable.

## `maxDiscoveryResults` (type: `integer`):

Maximum search results accepted as candidate ATS or career URLs before deduplication.

## `technologyKeywords` (type: `array`):

Optional technologies to match, such as AWS, GCP, Snowflake, React, Datadog, Kubernetes, or Airflow.

## `technologyMatchMode` (type: `string`):

Choose whether a company must match any or all requested technologies.

## `minimumOpenRolesPerCompany` (type: `integer`):

Require this many matching open roles before a company becomes a qualified result.

## `includeTechnologyEvidence` (type: `boolean`):

Return source URLs and evidence snippets for technologies found in job specifications or the company homepage.

## `includeContactRoute` (type: `boolean`):

Return only generic public company routes such as /contact, /careers, or a generic business email. Personal emails and personal profiles are never collected.

## `includeFirmographics` (type: `boolean`):

Extract publicly visible industry, headquarters, location, and company-size information when available.

## `includeJobDescription` (type: `boolean`):

Include cleaned descriptions. Disabled by default to reduce output size and run cost.

## `maxCompanies` (type: `integer`):

Maximum number of deduplicated employer records to return.

## `maxJobsPerCompany` (type: `integer`):

Maximum matching jobs kept for each employer.

## `sortBy` (type: `string`):

Choose the order in which qualified companies are written to the dataset.

## `countryCode` (type: `string`):

Optional ISO 3166-1 alpha-2 code used when a company has regional career pages.

## `proxyMode` (type: `string`):

Auto uses Apify Proxy when available and rotates sessions. Disable only for public API testing or low-volume direct targets.

## `proxyCountry` (type: `string`):

Optional ISO country code for the Apify proxy. Leave empty for automatic routing.

## `maxConcurrency` (type: `integer`):

Advanced control for parallel requests. Lower this if a source is rate-limiting the run.

## `requestTimeoutSeconds` (type: `integer`):

Advanced timeout for a single public request.

## Actor input object example

```json
{
  "discoveryMode": "both",
  "roleKeywords": [
    "data engineer"
  ],
  "locations": [],
  "workMode": "any",
  "seniority": [],
  "employmentTypes": [],
  "postedWithinDays": 7,
  "targetSources": [
    "auto"
  ],
  "seedCompanyDomains": [],
  "seedCareerUrls": [],
  "searchQueries": [],
  "searchProviders": [
    "duckduckgo",
    "bing"
  ],
  "maxDiscoveryResults": 50,
  "technologyKeywords": [],
  "technologyMatchMode": "any",
  "minimumOpenRolesPerCompany": 1,
  "includeTechnologyEvidence": true,
  "includeContactRoute": true,
  "includeFirmographics": true,
  "includeJobDescription": false,
  "maxCompanies": 500,
  "maxJobsPerCompany": 10,
  "sortBy": "intent_score",
  "countryCode": "",
  "proxyMode": "auto",
  "proxyCountry": "",
  "maxConcurrency": 8,
  "requestTimeoutSeconds": 20
}
```

# Actor output Schema

## `results` (type: `string`):

Download the Actor results from the default dataset.

# 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 = {};

// Run the Actor and wait for it to finish
const run = await client.actor("axiom-labs/hiring-intent-stack-radar").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 = {}

# Run the Actor and wait for it to finish
run = client.actor("axiom-labs/hiring-intent-stack-radar").call(run_input=run_input)

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

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

```

## CLI example

```bash
echo '{}' |
apify call axiom-labs/hiring-intent-stack-radar --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,axiom-labs/hiring-intent-stack-radar"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/zuafkVC0FppLhQHvv/builds/imlYwcKADFifQQtaw/openapi.json
