# ATS & Tech Detector (`garnet_puppet/ats-tech-detector`) Actor

Give it a list of company websites and find out which hiring platform each one uses - Greenhouse, Lever, Ashby, Workday and 10 more. Every match is checked for ownership before it is reported, so you get the company's own board and not a lookalike. Open role counts included.

- **URL**: https://apify.com/garnet\_puppet/ats-tech-detector.md
- **Developed by:** [Mehmet](https://apify.com/garnet_puppet) (community)
- **Categories:**
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $4.00 / 1,000 company resolveds

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

Give this Actor a list of company websites and it tells you which applicant tracking system each
one runs on, links straight to their job board, counts the open roles, and flags the companies
that quietly moved somewhere else.

### What does ATS & Tech Detector do?

Sales and recruiting teams keep lists of target companies. What those lists never contain is the
one field that makes them actionable: **where does this company actually post its jobs?**

Paste in `vercel.com`, `ramp.com`, `anthropic.com` and get back:

| Company | ATS | Board | Open roles |
|---|---|---|---|
| vercel.com | greenhouse | vercel | 83 |
| ramp.com | ashby | ramp | 128 |
| anthropic.com | greenhouse | anthropic | 61 |

Fourteen platforms are recognised: Greenhouse, Lever, Ashby, Workable, SmartRecruiters,
Recruitee, Personio, BambooHR, Teamtailor, Pinpoint, Rippling, Workday, Comeet and JOIN.

### Sample output

```json
{
  "domain": "vercel.com",
  "resolved": true,
  "sourceId": "greenhouse",
  "slug": "vercel",
  "boardUrl": "https://job-boards.greenhouse.io/vercel",
  "via": "signature",
  "verified": true,
  "confidence": 0.99,
  "evidence": "job-boards.greenhouse.io/vercel",
  "openJobs": 83,
  "careersRedirectsTo": null,
  "checkedAt": "2026-08-12T09:14:02.113Z"
}
```

### What makes this different

**1. It never guesses at your expense.** Board names are often derivable from a domain — but a
derived name can belong to a *different company that happens to share it*. Measured on real
data: a board found for `neon.tech` turned out to belong to a Brazilian fintech, and one found
for `windmill.dev` belonged to an unrelated HR startup in New York. Roughly one in five derived
matches was the wrong company.

So every derived match has to prove itself: the board must reference your domain, or link back
to your website. If it cannot, the row comes back `resolved: false` with the board name we saw,
so you can check it yourself. **You are only charged for companies whose board is proven.**

**2. It tells you who moved.** Each careers page is followed to its destination. When it lands on
a different company, that is reported in `careersRedirectsTo` — usually an acquisition. Real
examples this Actor surfaced: `neon.tech` → `databricks.com`, `stytch.com` → `twilio.com`,
`loom.com` → `atlassian.com`. Those companies are still on target lists everywhere, and they no
longer hire independently.

**3. It counts open roles.** A company with 80 open roles is a different prospect from one with
two. `openJobs` gives you that without a second tool.

### How to use it

1. Paste your company websites into **Company domains** — one per line, plain domains.
2. Run it. Every domain comes back as a row, resolved or not.
3. Export to CSV/JSON, or pipe it into Google Sheets, Slack, Zapier, Make or n8n.

For long lists you re-check periodically, turn on **Skip domains resolved in a previous run** —
already-resolved companies are skipped and not charged.

### Input configuration

| Field | What it does | Default |
|---|---|---|
| Company domains | Websites to look up | `vercel.com`, `ramp.com`, `anthropic.com` |
| Count open roles | Also return how many roles are open | On |
| Flag companies that moved | Detect acquisitions and rebrands | On |
| Skip domains resolved before | For repeat runs over long lists | Off |
| Proxy configuration | Not needed for these sources | Off |

### Pricing

You pay per company whose board is **proven**. Unresolved companies are free.

| Event | Price |
|---|---|
| Company resolved | $0.004 |

Looking up 500 companies where 350 resolve costs 350 × $0.004 = **$1.40**.

### Limits, stated plainly

**Roughly 8 in 10 companies resolve.** Measured on samples of tech companies chosen before
their ATS was known. The misses are not random — they fall into three groups:

- **Unsupported systems.** iCIMS, Gem, JazzHR and in-house tools cannot be resolved at all,
  and they are the bulk of the misses. If your list is heavy on those, expect a lower rate.
- **Board name not derivable + a JavaScript careers page.** When the board name cannot be
  guessed from the domain *and* the careers page renders its listings in the browser, the
  server sends no link for us to find.
- **Two platforms are structurally underivable.** Workday needs a tenant, a data centre
  number and a free-text site name; Comeet needs an account id and a separate token. Neither
  can be derived from a company name. If a link exists on the careers page it is picked up
  automatically; otherwise pass them explicitly.

**A miss is reported, not hidden.** An unresolved company comes back with
`resolved: false` and what was actually checked, so you can tell "no ATS found" apart from
"we did not look". You are only charged for companies that resolve.

**This Actor never guesses.** A board name that looks derivable is only reported once the
board is fetched and proven to belong to your domain.

### Frequently asked questions

**How many of my companies will resolve?**
It depends on the platforms your list uses. Measured on samples of tech companies chosen before
their ATS was known, roughly 8 in 10 resolved. Companies on an unsupported system — iCIMS, Gem,
JazzHR, or an in-house tool — cannot be resolved at all, and are the bulk of the misses.

**A company I know uses Greenhouse came back unresolved. Why?**
Most likely the board name is not derivable from the domain and the careers page renders its
listings in the browser, so the server sends no link to find. The row still tells you what was
checked. If you already know the board name, the sibling Actor **Career Site Job Scraper** takes
it directly.

**Two platforms behave differently.** Workday and Comeet addresses cannot be derived from a
company name at all — Workday needs a tenant, a data centre number and a site name; Comeet needs
an account id and a token. Both are picked up when the careers page links to them, but never
guessed.

**Is this affiliated with any of those platforms?**
No. This is an unofficial tool, not affiliated with or endorsed by any of them. All product
names are trademarks of their respective owners.

**Is this legal?**
It reads the same public pages and public job board endpoints that companies publish so their
openings can be found and indexed. It does not access private data and never uses a login.

# Actor input Schema

## `companyDomains` (type: `array`):

Company websites, one per line, e.g. vercel.com. Job board links are not needed - that is what this Actor works out for you.

## `includeJobCount` (type: `boolean`):

Also return how many roles are open on each board. Costs a little extra run time on very large boards.

## `detectMoves` (type: `boolean`):

Follow each careers page and report when it lands on a different company - a strong signal the company was acquired or rebranded.

## `incremental` (type: `boolean`):

Useful for long lists you re-check periodically. Skipped domains are not charged.

## `proxyConfiguration` (type: `object`):

Not needed for these sources. Change it only if a source starts blocking requests.

## Actor input object example

```json
{
  "companyDomains": [
    "vercel.com",
    "ramp.com",
    "anthropic.com"
  ],
  "includeJobCount": true,
  "detectMoves": true,
  "incremental": false,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

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

One item per company domain: which ATS it uses, the job board URL, open role count and acquisition flag.

## `runSummary` (type: `string`):

Counts for the whole run: what was delivered, what was skipped, what failed, and any warnings. Read this to see whether the run did what you expected.

# 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 = {
    "companyDomains": [
        "vercel.com",
        "ramp.com",
        "anthropic.com"
    ],
    "proxyConfiguration": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("garnet_puppet/ats-tech-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 = {
    "companyDomains": [
        "vercel.com",
        "ramp.com",
        "anthropic.com",
    ],
    "proxyConfiguration": { "useApifyProxy": False },
}

# Run the Actor and wait for it to finish
run = client.actor("garnet_puppet/ats-tech-detector").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 '{
  "companyDomains": [
    "vercel.com",
    "ramp.com",
    "anthropic.com"
  ],
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}' |
apify call garnet_puppet/ats-tech-detector --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,garnet_puppet/ats-tech-detector"
        }
    }
}

```

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/6R9xpchNUcegRSBEn/builds/8dIRUBldv4ewrJHCw/openapi.json
