# Company Domain Enrichment — Firmographics for Agents (`plugiverse/company-domain-profile`) Actor

Company enrichment / domain firmographics for AI agents: domain → JSON with name, description, logo, socials, tech stack, email provider, optional LEI/SEC CIK/Companies House IDs. Domain-to-company profile via Apify MCP. Failed lookups free. PPE + LIMITED_PERMISSIONS.

- **URL**: https://apify.com/plugiverse/company-domain-profile.md
- **Developed by:** [Plugiverse](https://apify.com/plugiverse) (community)
- **Categories:** Lead generation, AI, Developer tools
- **Security:** Limited permissions
- **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 profiles

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?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
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.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## 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.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Company Profile from Domain — Firmographics, Socials & Tech Stack API

Turn a **company domain** into one clean JSON record: company name, description, country, logo, the company's own **social links** (LinkedIn, X, GitHub, YouTube…), **tech stack**, **email provider** (from DNS), and optional **registry IDs** (LEI from GLEIF, SEC CIK, UK Companies House number). **Built for company-level data.** It does not look for personal emails, phone numbers or employee profiles. Free-text fields (such as `description`) are copied from the company's own site and may mention people.

### What it does and when to use it

Use it when you have a list of domains (CRM, lead list, an agent's research task) and want a quick company profile, with the source of each returned field listed in `provenance`.
Don't use it for people/contact discovery, for financials, or for sites behind a login.

### Use cases

Company Profile from Domain is for company-level data.

1. **List enrichment.** You have company domains from a CRM or a spreadsheet and want a name, description, country hint and the company's own social links on each row.
2. **Agent research.** An AI agent holds a batch of domains and needs one JSON profile per company, with a free error row for each domain that fails.
3. **Vendor and competitor tech.** You want the public tech stack and email provider of company sites, read from pages and DNS, not from a person.
4. **Registry IDs.** You want a public LEI, SEC CIK or UK company number when the site shows a legal name and the match is unambiguous.
5. **Messy inputs.** The list mixes bare domains, homepages, `www` hosts and `info@` addresses. Duplicates collapse to one registrable domain, and invalid entries stay as free error rows.

### Call it from an AI agent (Apify MCP)

This Actor runs on Apify. An agent finds and runs it through Apify's own MCP server at `https://mcp.apify.com` (tool reference: `https://docs.apify.com/mcp`). There is no separate API on this page.

1. Add `https://mcp.apify.com` to the MCP client, or pin this Actor with `https://mcp.apify.com?tools=plugiverse/company-domain-profile`. The hosted server uses the caller's existing Apify login (OAuth) or an existing Apify API token sent as a Bearer token. The Actor still runs on Apify. Apify's docs also describe a local stdio server (`npx @apify/actors-mcp-server`); Actors run on Apify in that mode too.
2. The agent calls `search-actors` with simple keywords such as `company domain profile`, `domain firmographics`, `company enrichment domain`, or `company-domain-profile`, or it uses the Store slug `plugiverse/company-domain-profile` directly. Apify documents that `search-actors` lists only free and pay-per-event Actors that pass its agent-safety filters. If this Actor is absent from search, call it by that slug, or use the pinned URL above. This page does not claim search will always return it.
3. `fetch-actor-details` returns the input schema, README and pricing. Read those before a run. The input is the same object as in the Input section. A sample is `{"domains": ["stripe.com", "shopify.com", "atlassian.com"]}`.
4. `call-actor` starts the run. Apify documents that this tool waits 30 seconds by default and at most 45 seconds, then returns the run status and storage IDs. It does not return the dataset rows inline. A short sample often finishes inside that wait. A long batch can outlast it. The agent then uses `get-actor-run` and `get-dataset-items` (Apify loads these with `call-actor`) to read rows. The run summary is the `SUMMARY` record in the run's key-value store.
5. The run bills the caller's Apify account at the event prices below. Connecting to the MCP server does not, by itself, add a charge from this Actor. Apify documents `maxTotalChargeUsd` inside `call-actor` `callOptions` as the way to cap a pay-per-event run. If `call-actor` returns an approval error, Apify's docs say that Actor needs a one-time approval before it will run. This page does not claim this Actor is exempt.

Failed lookups are **free** and come back as rows with `status: "error"` and a machine-readable `error.code`. With `failOnAllErrors` on (the default), a run in which every domain fails ends as FAILED, not as an empty success.
Minimal call: `{"domains": ["stripe.com"]}` costs about $0.006 (one profile plus tech stack) when both events apply.

### Input

| Field | Type | Default | Notes |
|---|---|---|---|
| `domains` | string\[] | required | Bare domains, URLs or info@ addresses. Lowercased; scheme, path and www removed. Duplicates removed. Up to 1000. Each failure is one free error row. 45 s limit per domain. |
| `include` | string\[] | `["techStack","socials"]` | Add `registry` (LEI/CIK/UK no.) or `roleEmails` (generic info@-style addresses only) |
| `companiesHouseApiKey` | secret string | – | Your own free key; enables UK registry matches |
| `maxPagesPerDomain` | int 1–5 | 3 | Homepage, then about/contact pages only if fields are missing |
| `failOnAllErrors` | bool | true | Run ends FAILED if every domain fails |

### Output (one row per input)

```json
{"input":"stripe.com","domain":"stripe.com","status":"ok","error":null,
 "company":{"name":"Stripe","nameMatchesDomain":true,"legalName":"Stripe, LLC","description":"Stripe powers online and in-person payment processing…","homepageUrl":"https://stripe.com/","language":"en","countryHint":null,"logoUrl":"…","foundingYear":null},
 "socials":{"linkedin":"https://www.linkedin.com/company/stripe","x":"https://twitter.com/stripe","github":"https://github.com/stripe","youtube":"https://youtube.com/@stripe","facebook":"https://www.facebook.com/StripeHQ","instagram":"https://www.instagram.com/stripehq","tiktok":null},
 "techStack":{"technologies":[{"name":"Next.js","category":"framework","confidence":0.75,"evidence":"html //_next/static//"}],"emailProvider":"Google Workspace","dnsVerifications":["atlassian","google","openai"]},
 "registry":{"lei":"549300CLHGIPTCYHQ143","matches":[{"source":"gleif","name":"STRIPE, LLC","score":1.0}]},
 "provenance":[{"field":"name","source":"https://stripe.com/ (schema.org Organization.name)"}],
 "notFound":["foundingYear","countryHint"],"pagesFetched":3,"billing":{"eventsCharged":["company-profile","tech-stack","registry-match"]}}
```

`status`: `ok` means name and description were found. `partial` means a name was found but no description. Any missing fields (including social profiles we could not attribute to the company) are listed in `notFound`. `error` means the lookup failed; see the error codes below.

#### Error codes (all free)

`INPUT_INVALID`, `DNS_NOT_FOUND`, `UNREACHABLE`, `TIMEOUT`, `HTTP_4XX`, `HTTP_5XX`, `ROBOTS_DISALLOWED`, `BLOCKED_OR_CAPTCHA`, `PARKED_DOMAIN`, `NOT_A_COMPANY_SITE` (also used for reserved example/test domains such as `example.com`), `NOT_HTML`, `INTERNAL_ERROR` (retryable), `CHARGE_LIMIT_REACHED`. Each error row carries a `message` and a `retryable` flag.

### Pricing (pay per event)

| Event | Price | When |
|---|---|---|
| `apify-actor-start` | $0.00005 | Synthetic start (Apify covers first 5s compute; charged per GB memory, min 1) |
| Company profile | $0.004 | A row with a company name (status ok/partial) |
| Tech stack | $0.002 | Tech stack or email provider returned |
| Registry match | $0.005 | An unambiguous LEI / CIK / UK number found |
Error rows: $0. Example: 100 domains with the default sections cost about $0.60. Duplicates (e.g. `stripe.com` and `https://www.stripe.com/about`) are charged once. The Actor stops cleanly at your run's maximum charge: a domain that can no longer be paid for comes back as a free `CHARGE_LIMIT_REACHED` row, and each row's `billing.eventsCharged` lists only events actually charged.

### Pricing examples per 1k

Prices are per successful event, not per domain requested. Error rows are $0. The event prices above are company profile $0.004 ($4 per 1,000 events), tech stack $0.002 ($2 per 1,000 events) and registry match $0.005 ($5 per 1,000 events).

| What 1,000 rows contain | Charge |
|---|---|
| 1,000 company-profile events (a name was found) | $4 |
| 1,000 tech-stack events (technologies or an email provider) | $2 |
| 1,000 registry-match events (an unambiguous LEI, CIK or UK company number) | $5 |
| 1,000 error rows (invalid input, timeout, unreachable, blocked, and the other error codes) | $0 |
| 1,000 domains, default sections, every domain returns a profile and a tech stack, no registry match | $6 |
| 1,000 domains where every row charges all three events | $11 |
| 800 domains return a profile and a tech stack, 200 come back as error rows | $4.80 |

A registry match is charged only when an unambiguous ID is found, not merely because `registry` was requested. The 100-domain example above ($0.60 with the default sections) is the same rate as $6 per 1,000. Duplicates are still one domain.

### Data sources and provenance

- The company's own public homepage and about/contact pages: schema.org JSON-LD, OpenGraph, `<title>`, links and response headers. robots.txt is obeyed (user agent `CompanyDomainProfileBot`) and checked separately for every host and redirect hop before any request; if robots.txt cannot be reached, the site is not fetched. At most 5 pages per domain, one request at a time, with a delay between requests, a 2 MB cap per page and a 45 s deadline per domain.
- Public DNS (MX/TXT): looked up via **Google Public DNS** DNS-over-HTTPS (`dns.google`), with the system resolver as a fallback. The looked-up domain name is therefore sent to Google.
- GLEIF LEI data (CC0). SEC EDGAR company tickers (public). UK Companies House API (your key). "Source: Companies House"; not affiliated with or endorsed by Companies House.

Company, product and service names used in this README (for example Stripe, Monzo, LinkedIn, X, GitHub, Google, GLEIF, SEC EDGAR and Companies House) are trademarks of their owners and are used only to describe data sources and examples. This Actor is not affiliated with, endorsed by or sponsored by any of them. LEI data is sourced from GLEIF under CC0; this Actor is not a GLEIF or LOU service.

### Privacy

Only company-level fields are returned. Personal LinkedIn profiles (`/in/…`) and personal email addresses are never output. X, GitHub, Instagram and Facebook links are returned only when the site declares them in schema.org `sameAs` or the handle matches the company's domain name, so a footer link to a founder's personal account is not output. Role addresses (info@, sales@…) are returned only when you ask for `roleEmails`. Per-run usage stats (origin, counts) contain no user data or input values.

### Terms, acceptable use and data protection

- **You are the controller.** You choose the domains and decide what happens to the results, so for any personal data in them (for example a sole trader's name, a generic contact address of a one-person business, or a name in a description) you are the controller and PLUGIVERSE SA LTD processes it for you only to run the Actor, as set out in the Apify Standard Actor Contract. You need your own lawful basis (for example legitimate interests under applicable data-protection laws such as the GDPR, UK GDPR or CCPA/CPRA), must give any transparency notice required by Article 14 GDPR, must keep only what you need, and must honour objections and other data subject rights. Leave `roleEmails` off unless you need it.
- **Company-level data only.** This Actor is meant for data about companies, not about individuals. Don't use it to profile, track or contact individual people, and don't combine its output with other data to do so.
- **Acceptable use.** Use it in line with applicable law, the Apify terms and the terms of the sites you look up. Don't use it for spam, harassment, or to get around access controls; bot-protected sites are reported as `BLOCKED_OR_CAPTCHA` and not bypassed.
- **robots.txt.** The crawler identifies itself as `CompanyDomainProfileBot` and obeys robots.txt. Site owners can block it with `User-agent: CompanyDomainProfileBot` / `Disallow: /`.
- **Opt-out and contact.** Site owners can block the crawler in robots.txt (see above) or ask for an opt-out or raise a question at support@plugiverse.biz or through the Issues tab on this Store page.
- **Terms that apply.** Your use of this Actor is governed by the Apify Standard Actor Contract between you and the publisher, PLUGIVERSE SA LTD, together with the Apify terms. Nothing in this README replaces those terms.
- **No warranty.** The Actor and its output are provided "as is" and "as available", without warranties of any kind, express or implied, including accuracy, completeness, timeliness, fitness for a particular purpose and non-infringement. Output comes from public websites and registries, may be incomplete, wrong or out of date, and must be checked independently before you rely on it for any decision.
- **Limitation of liability.** To the maximum extent permitted by law, PLUGIVERSE SA LTD's total liability arising out of or in connection with this Actor is limited as set out in the Apify Standard Actor Contract, and it is not liable for indirect or consequential loss, or loss of profits, data or business. Nothing limits liability that cannot be limited by law, including for death or personal injury caused by negligence or for fraud.
- **Your responsibility.** You are responsible for making sure your inputs, your use of the output, and any onward use (including marketing or outreach) are lawful, including data protection, e-privacy/direct-marketing rules and the terms of the sites and registries involved.
- **Not advice.** Output is information only. It is not legal, financial, credit, compliance or investment advice, and registry matches (LEI, CIK, UK company number) are automated name matches, not verified identity checks.
- Source code licence: proprietary, see `LICENSE` (Copyright (c) 2026 PLUGIVERSE SA LTD).

**Publisher.** This Actor is published by PLUGIVERSE SA LTD, a private limited company registered in England and Wales under company number 16937458. Registered office: Office 16270, 182-184 High Street North, East Ham, London, E6 2JA, United Kingdom. ICO registration number ZC229010. Not VAT registered. Support and opt-out requests: support@plugiverse.biz (or use the Issues tab on this page).

### FAQ

- **Why is `countryHint` null?** It is set only from schema.org addresses or a country-code TLD. We don't guess.
- **`nameMatchesDomain: false`?** The name may be a tagline (for example n26.com). Check it.
- **Why did a site fail with `BLOCKED_OR_CAPTCHA`?** The site serves a bot challenge. We don't try to get around it.

### Changelog

- 0.0.5: Document `apify-actor-start` PPE event; expand MCP `search-actors` keywords for firmographics/enrichment discovery.
- 0.1.2: Store examples and form prefills for every input (sample domains stripe.com, shopify.com, atlassian.com). A run of only invalid domains writes one free error row each. README: use cases, how an agent calls the Actor through Apify MCP, and prices per 1,000 events.
- 0.1.1: review fixes: robots.txt per origin and per redirect hop, per-domain deadline, streamed size cap, dedupe by domain, accurate billing, no personal social handles, reserved domains free, pinned build.
- 0.1.0: first version.

Not affiliated with or endorsed by GLEIF, the SEC or Companies House; LEI data from GLEIF (CC0).

# Actor input Schema

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

One company per entry: a bare domain, a URL, or an address such as info@stripe.com. Lowercased. Scheme, userinfo, port, path and a leading www are removed, then the registrable domain is used (other subdomains collapse too). Duplicates are removed. Maximum 1000 per run. Each entry has its own 45 second time limit. A failed entry is one free error row and does not stop the others. Invalid entries use error.code INPUT_INVALID.

## `include` (type: `array`):

company (name, description, country, logo) is always returned when a name is found. techStack: detected technologies and the email provider from DNS. socials: the company's own LinkedIn, X, GitHub, YouTube, Facebook, Instagram and TikTok links. registry: LEI (GLEIF), SEC CIK and UK company number (the UK number needs companiesHouseApiKey). roleEmails: generic addresses such as info@ only, never personal ones.

## `companiesHouseApiKey` (type: `string`):

Optional. Your own key from the Companies House developer portal. Used only when registry is included, and only for a UK company-number check. Leave blank if you do not need that check. The example text is a placeholder, not a key.

## `maxPagesPerDomain` (type: `integer`):

Homepage plus about or contact pages, fetched only when fields are still missing. robots.txt is obeyed. Integer from 1 to 5.

## `failOnAllErrors` (type: `boolean`):

When true, a run in which every domain fails ends as FAILED after the free error rows are written, instead of SUCCEEDED with only errors. One failed domain among successes does not fail the run.

## Actor input object example

```json
{
  "domains": [
    "stripe.com",
    "shopify.com",
    "atlassian.com"
  ],
  "include": [
    "techStack",
    "socials"
  ],
  "companiesHouseApiKey": "your-companies-house-api-key",
  "maxPagesPerDomain": 3,
  "failOnAllErrors": true
}
```

# Actor output Schema

## `overview` (type: `string`):

Default dataset, Overview view (domain, status, name, country, description, LinkedIn, email provider, error code). Full rows are described in dataset_schema.json.

## `summary` (type: `string`):

SUMMARY record in the default key-value store: counts and events charged for the run.

# 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",
        "shopify.com",
        "atlassian.com"
    ],
    "include": [
        "techStack",
        "socials"
    ],
    "companiesHouseApiKey": "",
    "maxPagesPerDomain": 3,
    "failOnAllErrors": true
};

// Run the Actor and wait for it to finish
const run = await client.actor("plugiverse/company-domain-profile").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",
        "shopify.com",
        "atlassian.com",
    ],
    "include": [
        "techStack",
        "socials",
    ],
    "companiesHouseApiKey": "",
    "maxPagesPerDomain": 3,
    "failOnAllErrors": True,
}

# Run the Actor and wait for it to finish
run = client.actor("plugiverse/company-domain-profile").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",
    "shopify.com",
    "atlassian.com"
  ],
  "include": [
    "techStack",
    "socials"
  ],
  "companiesHouseApiKey": "",
  "maxPagesPerDomain": 3,
  "failOnAllErrors": true
}' |
apify call plugiverse/company-domain-profile --silent --output-dataset

```

## MCP server setup

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

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/fC1M7SXmy5o6si0cm/builds/wc5osQtITjdbu9RN8/openapi.json
