# Company Domain Enrichment — Registration, DNS, Tech Stack & TLS (`accountable_eel/company-domain-enrichment`) Actor

One domain in, seven signals out: RDAP registration, DNS and email provider, tech stack, Shopify storefront presence, TLS certificate history, ATS hiring signal, and an email-route/provider fingerprint. Each source is billed separately, only when it actually returns data.

- **URL**: https://apify.com/accountable\_eel/company-domain-enrichment.md
- **Developed by:** [Adrian Voss](https://apify.com/accountable_eel) (community)
- **Categories:** Lead generation, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.80 / 1,000 domain registration matches

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

## Company Domain Enrichment

Feed in a company domain and get seven independent signals back in one call: domain
registration (via [RDAP](https://about.rdap.org)), DNS records and email provider (via
[Cloudflare DoH](https://developers.cloudflare.com/1.1.1.1/encryption/dns-over-https/)),
detected tech stack, Shopify storefront presence, TLS certificate history (via public
[Certificate Transparency logs](https://sslmate.com/certspotter/)), a hiring signal
detected across six ATS platforms, and an email-route/provider fingerprint. Each source
is an independent public API or passive check — no login for any of the seven — and
each is billed only when it actually returns data for that domain.

### Who it's for

The accountable\_eel catalogue sells company intelligence columns for outbound. Each actor takes a
list of domains or company identifiers and returns one flat, stably-named row per input —
firmographics, registry IDs, tech stack, email route, hiring activity — the shape a Clay table, an
n8n workflow, or an AI agent can consume without post-processing. Pricing is pay-per-event and
per-domain: a few tenths of a cent for a row that was actually found, and nothing for a
miss, so a list that doesn't enrich costs you next to nothing. Where an official source exists —
VIES, GLEIF, SEC EDGAR, Brønnøysund, PRH, RDAP — it is queried directly instead of scraped. No
seat licence, no monthly minimum, no credit system to decode.

This one is a composite: instead of running seven separate lookups against a domain list, it runs
all seven in one call and returns one row per domain, with each source's result nested under its
own key and billed independently.

### Why this one

- **Seven signals, one call, one row per domain.** You don't glue together seven actors or seven
  API calls client-side — `registration`, `dns`, `techStack`, `shopify`, `tlsCertificate`,
  `hiring`, and `emailRoute` all land in the same dataset row.
- **Official or primary sources, not scraped guesses.** Registration comes from RDAP, DNS from
  Cloudflare's resolver, TLS history from public Certificate Transparency logs, and hiring data
  from each ATS platform's own public API — the same sources this portfolio's single-purpose
  actors use.
- **You only pay for sources that return something.** A domain with no Shopify storefront costs
  nothing for the `shopify` source that run; a domain with no ATS board costs nothing for
  `hiring`. Check `sourcesFound` on each row to see exactly what was billed.
- **`columns` controls both output and cost.** Narrowing to the three sources you actually use
  isn't just a display filter — the unselected sources are never queried, so it's a real way to
  cut the per-domain price.
- **No proxies, no SMTP, nothing stored between runs.** All seven sources are plain HTTPS calls a
  cloud runtime can make directly; nothing about this actor requires residential IPs or an
  outbound mail connection.

### What you get

One dataset row per input domain. `found` is `true` if at least one of the seven sources
returned data; each source field is `null` when that specific source found nothing (a
non-Shopify site returns `shopify: null`, not an error).

**Top-level fields**

| Field | Type | Description |
|---|---|---|
| `query` | string | The domain as submitted |
| `found` | boolean | `true` if at least one of the seven sources returned data |
| `status` | string | `"OK"` or an error status for the row |
| `sourcesFound` | array of strings | Which sources actually returned data (and were billed) for this domain |
| `sourcesTried` | array of strings | Which sources were attempted (the sources selected via `columns`, minus any that errored before returning) |
| `scrapedAt` | ISO 8601 string | When this row was fetched |

**`registration`** — RDAP domain registration lookup

| Field | Type | Description |
|---|---|---|
| `domain` | string | The registered domain name, uppercased as returned by RDAP |
| `registrar` | string or null | Registrar name |
| `registrantOrg` | string or null | Registrant organization, when not privacy-redacted |
| `registeredAt` | ISO 8601 string or null | Original registration date |
| `expiresAt` | ISO 8601 string or null | Current expiry date |
| `status` | array of strings | RDAP status codes (e.g. `clientTransferProhibited`) |
| `nameservers` | array of strings | Nameserver hostnames |

**`dns`** — A and MX records via Cloudflare DoH

| Field | Type | Description |
|---|---|---|
| `domain` | string | The domain queried |
| `aRecords` | array of strings | IPv4 addresses from A records |
| `mxRecords` | array of strings | MX records as `"<priority> <host>."` |
| `emailProvider` | string or null | `"Google Workspace"`, `"Microsoft 365"`, `"other"`, or `null` if there are no MX records |

**`techStack`** — homepage HTML/header signature match

| Field | Type | Description |
|---|---|---|
| `domain` | string | The domain checked |
| `detectedCount` | number | Count of signatures matched |
| `detected` | array of objects | Each entry is `{ name, category }`, e.g. `{ "name": "Next.js", "category": "framework" }` |

**`shopify`** — storefront confirmation via `/products.json`

| Field | Type | Description |
|---|---|---|
| `domain` | string | The domain checked |
| `isShopify` | boolean | Always `true` when this object is present (it's `null` at the top level otherwise) |
| `sampleProductCount` | number | Number of products returned by the probe (up to 10) |
| `sampleProducts` | array of objects | Up to 5 entries, each `{ title, vendor }` |

**`tlsCertificate`** — current certificate + Certificate Transparency history

| Field | Type | Description |
|---|---|---|
| `domain` | string | The domain checked |
| `currentIssuer` | string or null | Issuer name of the most recent certificate |
| `currentNotBefore` | ISO 8601 string or null | Validity start of the most recent certificate |
| `currentNotAfter` | ISO 8601 string or null | Validity end of the most recent certificate |
| `currentSanCount` | number | Count of subject alternative names on the current certificate |
| `historicalCertCount` | number | Total certificates ever logged for this domain in CT logs |

**`hiring`** — ATS board detection across six platforms

| Field | Type | Description |
|---|---|---|
| `domain` | string | The domain checked |
| `atsDetected` | boolean | Always `true` when this object is present |
| `atsPlatform` | string | The platform with the most open roles, when more than one matched |
| `atsPlatforms` | array of strings | Every platform that had a live board (usually one: `greenhouse`, `lever`, `ashby`, `workable`, `smartrecruiters`, `personio`) |
| `openRoles` | number | Total open roles across matched platforms |
| `roleCountsByDepartment` | object | Role counts keyed by department name (or `"Unspecified"`) |
| `hiringFor` | object | Keyed by job family (`sales`, `engineering`, `marketing`, `customer-success`, `executive` by default, or your `hiringForGroups`); each value is `{ hiring: boolean, count: number }` |
| `newestPostingAt` | ISO 8601 string or null | Publish date of the most recent posting found |
| `postingsLast30d` | number | Postings published in the last 30 days |
| `postingsPrev30d` | number | Postings published in the 30 days before that |
| `velocity30d` | number or null | `postingsLast30d / postingsPrev30d`, rounded to 2 decimals; `null` if the prior window has zero postings |
| `sampleTitles` | array of strings | Up to 5 most recent distinct job titles |

**`emailRoute`** — MX/provider fingerprint, no SMTP

| Field | Type | Description |
|---|---|---|
| `domain` | string | The domain checked |
| `hasMxRecord` | boolean | Whether the domain has explicit MX records |
| `mxHosts` | array of strings | MX hostnames (empty if mail routes via the bare A record) |
| `emailProvider` | string or null | `"Google Workspace"`, `"Microsoft 365"`, `"Zoho Mail"`, `"Mailgun"`, `"SendGrid"`, `"Proton Mail"`, `"other"`, or `null` |
| `isDisposableDomain` | boolean | Checked against a community-maintained disposable-domain blocklist, refreshed each run |

### Price

- **Domain registration match**: $5 per 1,000 domains
- **DNS match**: $5 per 1,000 domains
- **Tech stack match**: $5 per 1,000 domains
- **Shopify storefront match**: $5 per 1,000 domains
- **TLS certificate match**: $5 per 1,000 domains
- **Hiring signal match**: $5 per 1,000 domains
- **Email route match**: $5 per 1,000 domains

Plus a $0.005 start fee per run. Each event above is billed independently, only when it actually returns data — misses (`found:false`) are never charged.

This is a composite actor, so it doesn't bill per domain — it bills per source that returns
data for that domain, and there are seven of them. At the FREE tier ($0.005 per source), the
worst case for a single domain is all seven sources hitting: **7 × $0.005 = $0.035 for that one
domain**, before volume discounts bring the per-source price down to $0.0038 on paid tiers. Most
domains will land somewhere below that — a domain with no Shopify storefront and no ATS board
only gets billed for the sources that actually found something.

Run 1,000 domains and every one hits all seven sources, and you're looking at up to **$35** (plus
the one-time $0.005 actor start) — that's the ceiling, not the typical case, since `shopify` and
`hiring` in particular miss on most domains. Compare that ceiling to a credit-based enrichment
platform: the same 1,000 rows there run **$80–$400**. Use `columns` to drop sources you don't
need and the real number falls further, since a source that isn't selected is never queried or
billed.

### How to use

1. **In the Apify Console.** Open the actor page and click **Start** — the `domains` field is already pre-filled with a working example. Results land in the run's dataset as soon as each item is found.
2. **Via the API.** Call it directly with a POST request — no Console needed once you have an API token:
   ```bash
   curl "https://api.apify.com/v2/acts/accountable_eel~company-domain-enrichment/run-sync-get-dataset-items?token=<YOUR_TOKEN>" \
     -X POST \
     -H "Content-Type: application/json" \
     -d '{"domains":["stripe.com"]}'
   ```
3. **On a schedule.** Save this actor as an Apify **Task** with the input you want, then add a **Schedule** (hourly, daily, weekly) so it runs on its own — no server of your own required.

1) Paste a list of domains into `domains` — one per line, bare (`stripe.com`) or full URL
   (`https://stripe.com`) both work.
2) Turn on `testRun` first to check your list against just the first 5 domains before committing
   to a full run.
3) Use `columns` to pick which of the seven sources you actually want. Every source you drop is
   neither queried nor billed for that run — this is the main lever for controlling cost.
4) Read the result: one row per domain, with each selected source nested under its own key
   (`row.registration`, `row.dns`, `row.techStack`, and so on), `null` when that source found
   nothing. Check `sourcesFound` on the row to see exactly what was billed.
5) If you use the `hiring` source, optionally replace the default five job families with
   `hiringForGroups` to match the segments you actually sell into.

### Input

```json
{
  "domains": [
    "stripe.com"
  ]
}
```

One company domain per line. Each domain is checked against seven independent sources — you're only charged for the ones that actually return something. Accepted formats: stripe.com, https://stripe.com.

```json
{
  "domains": ["stripe.com"],
  "testRun": false,
  "onlyFound": false,
  "maxConcurrency": 5
}
```

`domains` is a list of company domains (a bare domain or a full URL both work — `www.`
and the path are stripped automatically). Each domain is checked against all seven
sources; one dataset row is returned per domain, and you're only charged for the
sources that actually return something for it. Turn on `testRun` to try your list
against just the first 5 domains before running the full batch. Optional
`includeKeywords` / `excludeKeywords` filter rows by content, `maxResults` caps the run
early, `columns` lets you pick which of the seven sources to include, and
`hiringForGroups` customizes the job families the `hiring` source reports on.

### Sample output

| query | found | status | registration | dns | techStack | shopify | tlsCertificate | hiring | emailRoute | scrapedAt |
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
| stripe.com | true | OK | {"domain":"STRIPE.COM","registrar":"SafeNames Ltd.","registrantOrg":null,"registeredAt":"1995-09-12T04:00:00Z","expiresAt":"2027-09-11T04:00:00Z","status":\["client delete prohibited","client transfer prohibited","client update prohibited","server delete prohibited","server transfer prohibited","server update prohibited"],"nameservers":\["NS-1087.AWSDNS-07.ORG","NS-1882.AWSDNS-43.CO.UK","NS-423.AWSDNS-52.COM","NS-705.AWSDNS-24.NET"]} | {"domain":"stripe.com","aRecords":\["198.137.150.161","198.202.176.161"],"mxRecords":\["10 aspmx.l.google.com.","20 alt1.aspmx.l.google.com.","20 alt2.aspmx.l.google.com.","30 aspmx2.googlemail.com.","30 aspmx3.googlemail.com."],"emailProvider":"Google Workspace"} | {"domain":"stripe.com","detectedCount":1,"detected":\[{"name":"Next.js","category":"framework"}]} | <shopify storefront> | {"domain":"stripe.com","currentIssuer":"C=US, O=DigiCert Inc, CN=DigiCert Global G2 TLS RSA SHA256 2020 CA1","currentNotBefore":"2026-08-17T00:00:00Z","currentNotAfter":"2026-12-10T23:59:59Z","currentSanCount":2,"historicalCertCount":22} | {"domain":"stripe.com","atsDetected":true,"atsPlatform":"greenhouse","atsPlatforms":\["greenhouse"],"openRoles":589,"roleCountsByDepartment":{"1185 Account Executives (EMEA)":18,"Global Operations":18,"8811 Product Design":13,"7112 Data Science":11,"1175 Enterprise - Account Executives (NA)":10,"2317 Marketing - PMM":10,"8113 Brand Studio":9,"1195 Account Executives (APAC)":8,"1340 Customer Success Management":8,"1652 Platforms - Account Executives (NA)":8,"1160 Partner Solution Engineering":7,"1630 Alliances & Channels":7,"8504 Bridge - R\&D":7,"8548 Payins - Eng":7,"9001 Privy - R\&D":7,"1151 Solutions Architecture (AMER)":6,"1642 Product Sales - MaaS":6,"1651 Velocity - Account Executives (NA)":6,"3130 Risk & Reward":6,"3313 SDC - Financial Crimes":6,"8122 Data Foundations":6,"8414 MerchantXP - Eng":6,"8512 Terminal - Eng":6,"8560 Bank Connections - Eng":6,"1150 Solutions Architecture":5,"1154 Specialized Solutions Architecture":5,"1510 Global Business Services":5,"2314 Performance Marketing":5,"2315 Marketing - Marketing Operations":5,"2413 Communications":5,"3513 Core Product Partnerships":5,"4128 SDC - Product Support":5,"4145 Support Products - Eng":5,"4378 SDC - Fraud Operations":5,"4892 Risk Operations Enablement":5,"6220 Executive Operations":5,"6420 Accounting":5,"6480 Internal Audit":5,"8125 Core Compute":5,"8612 Security Infrastructure":5,"1130 Global Sales Development Mgrs":4,"1134 APAC Sales Development Reps":4,"1140 Professional Services":4,"1170 GEO Sales HQ (NA)":4,"1520 Sales Operations (SS\&O)":4,"1653 Startups - Account Executives (NA)":4,"3311 FinCRO":4,"4148 Technical Account Management, Support & Services - APAC":4,"4712 SDC - Accelerate":4,"4896 Fraud Operations":4,"5902 Tax Autofile":4,"6520 Recruiting":4,"8212 ML Foundations":4,"8538 MMS APIs & Experiences - PM":4,"8555 Payments Globalization - PM":4,"8570 Consumer Network - Eng":4,"8813 Web Presence & Platform":4,"9014 Metronome - R\&D":4,"1141 AMER Delivery":3,"1142 APAC Delivery":3,"1152 Solutions Architecture (EMEA)":3,"1512 Global Sales Enablement":3,"1530 GTM Industries":3,"1641 Product Sales - RFA ex Billing":3,"3131 Risk Supportability Strategy":3,"4130 Technical Account Management, Support & Services - AMER":3,"4135 SDC - Marketing":3,"4138 SDC - Tech Ops":3,"4204 SDC - MonOps":3,"4900 Support Eng & PM":3,"6215 Colds Program - G\&A":3,"6360 Product & Partnering Legal":3,"6410 Treasury Finance":3,"6430 Tax":3,"6444 Deal Pricing":3,"6451 COE F\&S (SDC)":3,"6620 Workplace Services":3,"7420 Finance Systems":3,"8217 Risk Engineering":3,"8259 Risk Tech Program Management & Other":3,"8412 Billing Products":3,"8514 Connect - Eng":3,"8546 Treasury for Platforms - Eng":3,"8611 Security Analytics":3,"1133 EMEA Sales Development Reps":2,"1135 Accelerate":2,"1342 Payment Performance":2,"1640 Product Sales - Payments":2,"1644 Product Sales - Prime Billing":2,"2313 Marketing - APAC":2,"3132 Risk Strategy":2,"3511 Financial Services Partnerships":2,"3514 Regional Product Partnerships":2,"3710 Startup Product":2,"4129 SDC - User Policy Operations":2,"4137 SDC - Legal Operations":2,"4150 Technical Support":2,"4168 SDC - Credit Operations":2,"4193 Financial Crimes Operations":2,"4203 BFin - Accounting (SDC)":2,"4374 SDC - Partner Risk Operations":2,"4899 SDC - Bridge RiskOps":2,"5112 General University":2,"6311 Data Protection & Privacy":2,"6320 Commercial Legal":2,"6427 Procurement":2,"6452 Sales Comp":2,"6513 People Systems & Solutions":2,"6515 People Consultants":2,"6526 University Recruiting":2,"6550 People Partners":2,"7312 CorpTech Customer Success":2,"8127 Core Infrastructure":2,"8186 Service Platform":2,"8260 Risk and Compliance Platform PM":2,"8262 APAC - PM":2,"8415 Revenue and Finance Automation":2,"8417 Accounting Products":2,"8516 Payments Global":2,"8551 OAP - Eng":2,"8552 PayIntel - PM":2,"8554 Payments Experiences - PM":2,"8569 MerchantXP - PM":2,"8614 Office of the CISO & Partnership":2,"8910 Technical Program Management":2,"8916 Growth - Eng":2,"1131 Vendor Mgmt and SD PM":1,"1132 AMER Sales Development Reps":1,"1143 EMEA Delivery":1,"1153 Solutions Architecture (APAC)":1,"1180 GEO Sales HQ (EMEA)":1,"1190 GEO Sales HQ (APAC)":1,"1540 Global Sales & Business Ops HQ":1,"1643 Product Sales - Billing":1,"1645 Product Sales - Metronome":1,"1650 AI GTM Strategy & Solutions":1,"2222 Corporate Development":1,"2326 Bridge - Marketing":1,"3110 User Policy Operations":1,"3133 Risk Onboarding Strategy":1,"3134 Fraud Risk Strategy":1,"3510 CBO Admin":1,"4119 Product Support":1,"4141 SDC - Central Operations Enablement":1,"4147 Technical Account Management, Support & Services - EMEA":1,"4160 SDC - Managed Operations: Issuing":1,"4176 Support S\&A":1,"4199 Consumer Operations - SDC":1,"4401 Merchant Acquiring Bank - Legal":1,"4516 SDC - Bridge":1,"4890 Credit Operations":1,"4891 Partner Risk Operations":1,"6313 EMEA Regulatory Affairs":1,"6314 Public Policy":1,"6390 Corporate Security":1,"6425 Finance Operations":1,"6441 Corporate F\&S":1,"6443 GTM F\&S":1,"6447 Product Pricing":1,"6448 Payments & Risk F\&S":1,"6449 CTO Finance & Strategy":1,"6482 SOX":1,"6490 BizOps and Compass":1,"6511 People Strategy & Enablement":1,"6512 People Analytics & Research":1,"6514 People Operations SDC":1,"6516 Employee Relations":1,"6522 Talent & Careers":1,"6523 Recruiting Enablement":1,"6532 Benefits":1,"6610 Food":1,"8116 Developer Platform - Eng":1,"8123 Core Infra Admin":1,"8126 Developer Infrastructure":1,"8129 Global Networking":1,"8134 Operations Platform":1,"8216 Risk Onboarding and Trusted Users":1,"8250 Connect - PM":1,"8256 Issuing - PM":1,"8505 Bridge - G\&A":1,"8506 Bridge - S\&O":1,"8511 PayIntel - Eng":1,"8513 Payments Experience - Eng":1,"8515 Capital - Eng":1,"8526 Product Experience Operations":1,"8535 Risk Credit & Fraud":1,"8539 MMS Product - Eng":1,"8556 LPM Core - Eng":1,"8571 Ecosystem Product":1,"8573 Payments, Risk, and Support Admin":1,"8582 Optimized Checkout - Eng":1,"8589 Bridge - S\&M":1,"8596 Tax Products":1,"8613 Data Privacy":1,"8712 Enterprise Engine":1,"8803 Partner Products":1,"8917 Growth - PM":1,"9003 Privy - S\&O":1,"Tech":1},"hiringFor":{"sales":{"hiring":true,"count":106},"engineering":{"hiring":true,"count":168},"marketing":{"hiring":true,"count":37},"customer-success":{"hiring":true,"count":16},"executive":{"hiring":true,"count":21}},"newestPostingAt":"2026-08-26T01:01:51.000Z","postingsLast30d":208,"postingsPrev30d":109,"velocity30d":1.91,"sampleTitles":\["Program Manager, Risk Operations GTM Enablement","Specialist Solutions Architect, Payments (Mandarin Speaking)","Product Manager, Cash Platform","Account Executive, Strategic Platform Partnerships","Account Executive, Enterprise Platforms, Tier 2 Grower"]} | {"domain":"stripe.com","hasMxRecord":true,"mxHosts":\["aspmx.l.google.com","alt1.aspmx.l.google.com","alt2.aspmx.l.google.com","aspmx2.googlemail.com","aspmx3.googlemail.com"],"emailProvider":"Google Workspace","isDisposableDomain":false} | 2026-08-26T06:00:25.215Z |

One row per domain, for example:

```json
{
  "query": "stripe.com",
  "found": true,
  "status": "OK",
  "registration": {
    "domain": "STRIPE.COM",
    "registrar": "MarkMonitor Inc.",
    "registrantOrg": "Stripe, Inc.",
    "registeredAt": "2010-11-24T02:36:59Z",
    "expiresAt": "2030-11-24T02:36:59Z",
    "status": ["clientTransferProhibited"],
    "nameservers": ["NS1.STRIPE.COM", "NS2.STRIPE.COM"]
  },
  "dns": {
    "domain": "stripe.com",
    "aRecords": ["104.18.24.44"],
    "mxRecords": ["1 aspmx.l.google.com."],
    "emailProvider": "Google Workspace"
  },
  "techStack": {
    "domain": "stripe.com",
    "detectedCount": 2,
    "detected": [{ "name": "React", "category": "framework" }, { "name": "Cloudflare", "category": "cdn" }]
  },
  "shopify": null,
  "tlsCertificate": {
    "domain": "stripe.com",
    "currentIssuer": "Let's Encrypt",
    "currentNotBefore": "2026-07-01T00:00:00Z",
    "currentNotAfter": "2026-09-29T00:00:00Z",
    "currentSanCount": 3,
    "historicalCertCount": 214
  },
  "hiring": {
    "domain": "stripe.com",
    "atsDetected": true,
    "atsPlatform": "greenhouse",
    "atsPlatforms": ["greenhouse"],
    "openRoles": 412,
    "roleCountsByDepartment": { "Engineering": 180, "Sales": 90, "Unspecified": 60 },
    "hiringFor": {
      "sales": { "hiring": true, "count": 90 },
      "engineering": { "hiring": true, "count": 180 },
      "marketing": { "hiring": true, "count": 12 },
      "customer-success": { "hiring": true, "count": 8 },
      "executive": { "hiring": true, "count": 5 }
    },
    "newestPostingAt": "2026-08-20T12:00:00.000Z",
    "postingsLast30d": 34,
    "postingsPrev30d": 21,
    "velocity30d": 1.62,
    "sampleTitles": ["Senior Software Engineer", "Account Executive", "Product Marketing Manager"]
  },
  "emailRoute": {
    "domain": "stripe.com",
    "hasMxRecord": true,
    "mxHosts": ["aspmx.l.google.com"],
    "emailProvider": "Google Workspace",
    "isDisposableDomain": false
  },
  "sourcesFound": ["registration", "dns", "techStack", "tlsCertificate", "hiring", "emailRoute"],
  "sourcesTried": ["registration", "dns", "techStack", "shopify", "tlsCertificate", "hiring", "emailRoute"],
  "scrapedAt": "2026-08-21T10:00:00.000Z"
}
```

Each source is `null` when that source specifically returned nothing (e.g. `shopify` is
`null` for a non-Shopify site) — and only sources with real data are charged. A domain
where every source misses still gets a row (`"found": false`), so you always get one
row per input, but nothing is billed for it.

### Use it from Clay, n8n, Make, or an AI agent

This actor runs synchronously over plain HTTP — call it directly from a script, a workflow tool, or an AI agent, no Apify Console needed once you have an API token.

```bash
curl "https://api.apify.com/v2/acts/accountable_eel~company-domain-enrichment/run-sync-get-dataset-items?token=<YOUR_TOKEN>" \
  -X POST \
  -H "Content-Type: application/json" \
  -d '{"domains":["stripe.com"]}'
```

**n8n.** Add an HTTP Request node: Method `POST`, URL `https://api.apify.com/v2/acts/accountable_eel~company-domain-enrichment/run-sync-get-dataset-items?token=<YOUR_TOKEN>`, Body Content Type `JSON`, JSON Body `{"domains":["stripe.com"]}` (swap in an expression from an earlier node for a real value).

**Clay.** Add an "HTTP API" column: Method `POST`, URL `https://api.apify.com/v2/acts/accountable_eel~company-domain-enrichment/run-sync-get-dataset-items?token=<YOUR_TOKEN>`, Body `{"domains":["{{domain}}"]}`, mapping the row's domain into the `domains` array.

**MCP.** In Claude, Cursor, or any MCP client with the Apify MCP server, ask for "Company Domain Enrichment API — RDAP, DNS, Tech Stack, TLS" — the agent will find and run this actor.

### Tips

- **Use `columns` to control cost, not just output width.** If you only care about tech stack
  and hiring signal, select just those two — the other five sources are never queried, so you're
  not paying for RDAP or TLS lookups you're going to ignore anyway.
- **Customize `hiringForGroups` to your own segments.** The default five families (sales,
  engineering, marketing, customer-success, executive) are a starting point — replace them with
  the job families that map to how you actually segment accounts, one per line as `name:
  keyword, keyword`.
- **Run `testRun` before a big batch.** Five domains is enough to confirm your list format and
  see what a typical row looks like before you commit to the full run and its full cost.
- **Check `sourcesFound` vs. `sourcesTried` on every row**, not just `found`. A domain can be
  `found: true` from a single hit (say, just `registration`) while five other sources came back
  empty — `sourcesFound` tells you exactly what you paid for.
- **Don't expect `shopify` or `hiring` to hit on most B2B domains.** They're conditional signals
  by nature — a services company with no e-commerce storefront and no public ATS board will
  legitimately return `null` for both, at no charge.

### vs. alternatives

| | What it costs | What you get | Trade-off |
|---|---|---|---|
| **This actor** (`company-domain-enrichment`) | $0.005 per source that returns data (down to $0.0038 on paid tiers), $0.005 actor start, nothing for a miss — up to $0.035 per domain if all seven sources hit | Registration, DNS/email provider, tech stack, Shopify presence, TLS certificate history, ATS hiring signal, and email route, nested in one row per domain | Each source is a focused subset (10 tech-stack signatures, 6 ATS platforms, no SMTP verification) — built for enrichment breadth, not exhaustive single-source depth. |
| **Clay** | $0.08–$0.40 per enriched row in credits, on top of a seat | A whole enrichment workspace — waterfalls across dozens of providers, plus the table and the sequencing around it | If you want one place that does everything and you're not counting rows, that's Clay. This is one column, priced per column, callable *from* Clay via its HTTP step. |
| **BuiltWith** | From $295/month | Historic tech data going back years, plus lead lists filtered by technology | If you need "every site that added Shopify last quarter", that's a database question and BuiltWith answers it. This answers "what is this one domain running, right now". |
| **Doing it yourself** | Your time + seven endpoints to integrate, rate-limit, and keep working as RDAP registries, ATS APIs, and CT log providers change their responses | The same data | This actor absorbs the maintenance: seven fetchers, retry/timeout handling, and a stable field shape that doesn't break when one upstream API changes its response format. |

Prices for third-party tools are their published list prices as of August 2026 and are not
tracked here — check the vendor before relying on the comparison.

### FAQ

**What happens if a domain doesn't match any of the seven sources?**
You still get a row (`found: false`), but nothing is billed — `Actor.charge()` only fires in the
branch where a source actually returns data, so a list full of parked domains or typos costs you
next to nothing.

**Do I need API keys or proxies for any of the seven sources?**
No. RDAP, Cloudflare DoH, the domain's own homepage, the six ATS platforms' public job-board
APIs, and public Certificate Transparency logs are all free and public. This actor also runs
with `noProxy: true` — none of the seven checks needs a residential or datacenter proxy.

**Are there rate limits or a concurrency I should worry about?**
`maxConcurrency` controls how many domains are processed in parallel (default 5) — raise it for
a faster run against a large list, or lower it if you're seeing timeouts from a slow upstream
source. There's no fixed per-run cap on domain count.

**Is any of this data cached or stored between runs?**
No. Every field is fetched live at run time from its source — RDAP, DNS, the domain's current
homepage, current CT log state, each ATS platform's current board, current MX records. Run the
same domain twice on different days and you may get different results (a new TLS cert, an
updated hiring count) because nothing is cached.

**Is this GDPR-relevant, and is it safe to run against EU company domains?**
The data returned is public registration (RDAP), public DNS, and public job postings — sources
that are, by design, published for public lookup. This actor doesn't return personal data about
individuals; `registrantOrg` reflects a company's registrant name when the registry doesn't
redact it. You're still responsible for how you use enriched company data downstream.

**Can I run this on a schedule to monitor a list of domains?**
Yes — set up an Apify schedule against this actor with the same `domains` input and a cadence
that fits your use case (weekly is common for hiring-signal or TLS-renewal monitoring). There's
no built-in delta tracking between runs; each run returns the current state, not what changed
since the last one.

**Can an AI agent call this directly?**
Yes — it's built for that. Any MCP client with the Apify MCP server can find and run this actor
by name ("Company Domain Enrichment API — RDAP, DNS, Tech Stack, TLS"), or you can call the
`run-sync-get-dataset-items` HTTP endpoint directly, as shown above.

**What's `hiringForGroups` actually for?**
It replaces the five default job families the `hiring` source reports on (sales, engineering,
marketing, customer-success, executive) with whatever segments you sell into — one line per
family as `name: keyword, keyword`. If you sell to procurement teams, for instance, you could add
a `procurement: procurement, sourcing, supply chain` line and every row's `hiring.hiringFor` will
report a count for it.

### Related actors

- **[Tech Stack Lookup](https://apify.com/accountable_eel/tech-stack-lookup)** — the full signature
  catalog (30+ technologies) if this actor's focused 10-signature subset isn't enough detail on
  its own.
- **[Company Registry Unified Lookup](https://apify.com/accountable_eel/company-registry-unified-lookup)**
  — for company identifiers instead of domains: VAT numbers, LEI codes, and national company
  registries (VIES, GLEIF, SEC EDGAR, Brønnøysund, PRH).
- **[Email Deliverability Check](https://apify.com/accountable_eel/email-deliverability-check)** —
  the standalone version of this actor's `emailRoute` source, with the same MX/provider
  fingerprint and disposable-domain check, run on its own.

# Actor input Schema

## `domains` (type: `array`):

One company domain per line. Each domain is checked against seven independent sources — you're only charged for the ones that actually return something. Accepted formats: stripe.com, https://stripe.com. You're only charged for the ones we actually find — a miss costs nothing.

## `testRun` (type: `boolean`):

Turn this on to test your input on a small sample before running the full list. Turn it off to process everything.

## `onlyFound` (type: `boolean`):

Only keep rows where something was actually found. Misses are always free, whether or not you show them here.

## `includeKeywords` (type: `array`):

Optional. Only keep results that mention at least one of these words (e.g. a job title, a city, a product name). Leave empty to keep everything.

## `excludeKeywords` (type: `array`):

Optional. Drop any result that mentions one of these words. Leave empty to skip nothing.

## `maxResults` (type: `integer`):

Optional. Stop the run once this many results have been found — useful for a quick, cheap sample. Leave blank for no limit.

## `hiringForGroups` (type: `array`):

Used by the "hiring" source. One job family per line, as "family name: keyword, keyword" — each domain is then reported as hiring (or not) for that family, with a count. Keywords match inside the job title and case does not matter, so "engineer" also catches "Engineering Manager". Leave as-is for the five defaults, or replace them with your own segments.

## `columns` (type: `array`):

Choose which sources to check. Only the sources you select here are checked — and only the ones that actually return data are billed. All are included by default.

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

Parallel requests. Keep conservative — this target has no browser fallback, so getting blocked costs more than slow-and-steady.

## Actor input object example

```json
{
  "domains": [
    "stripe.com"
  ],
  "testRun": false,
  "onlyFound": false,
  "includeKeywords": [],
  "excludeKeywords": [],
  "hiringForGroups": [
    "sales: sales, account executive, business development, sdr, bdr, account manager, revenue",
    "engineering: engineer, developer, software, devops, sre, data scientist, machine learning, architect",
    "marketing: marketing, demand generation, growth, content, brand, seo, communications",
    "customer-success: customer success, customer experience, customer support, technical support, implementation, onboarding, solutions consultant",
    "executive: chief, head of, vp, vice president, director, president"
  ],
  "columns": [
    "registration",
    "dns",
    "techStack",
    "shopify",
    "tlsCertificate",
    "hiring",
    "emailRoute"
  ],
  "maxConcurrency": 5
}
```

# Actor output Schema

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

No description

# 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 = {
    "domains": [
        "stripe.com"
    ],
    "includeKeywords": [],
    "excludeKeywords": [],
    "hiringForGroups": [
        "sales: sales, account executive, business development, sdr, bdr, account manager, revenue",
        "engineering: engineer, developer, software, devops, sre, data scientist, machine learning, architect",
        "marketing: marketing, demand generation, growth, content, brand, seo, communications",
        "customer-success: customer success, customer experience, customer support, technical support, implementation, onboarding, solutions consultant",
        "executive: chief, head of, vp, vice president, director, president"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("accountable_eel/company-domain-enrichment").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 = {
    "domains": ["stripe.com"],
    "includeKeywords": [],
    "excludeKeywords": [],
    "hiringForGroups": [
        "sales: sales, account executive, business development, sdr, bdr, account manager, revenue",
        "engineering: engineer, developer, software, devops, sre, data scientist, machine learning, architect",
        "marketing: marketing, demand generation, growth, content, brand, seo, communications",
        "customer-success: customer success, customer experience, customer support, technical support, implementation, onboarding, solutions consultant",
        "executive: chief, head of, vp, vice president, director, president",
    ],
}

# Run the Actor and wait for it to finish
run = client.actor("accountable_eel/company-domain-enrichment").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 '{
  "domains": [
    "stripe.com"
  ],
  "includeKeywords": [],
  "excludeKeywords": [],
  "hiringForGroups": [
    "sales: sales, account executive, business development, sdr, bdr, account manager, revenue",
    "engineering: engineer, developer, software, devops, sre, data scientist, machine learning, architect",
    "marketing: marketing, demand generation, growth, content, brand, seo, communications",
    "customer-success: customer success, customer experience, customer support, technical support, implementation, onboarding, solutions consultant",
    "executive: chief, head of, vp, vice president, director, president"
  ]
}' |
apify call accountable_eel/company-domain-enrichment --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,accountable_eel/company-domain-enrichment"
        }
    }
}

```

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/xjFtZTaszBRPqPEfF/builds/GaPFUBz8cNeSF5BKT/openapi.json
