# Company Enrichment — Domain to Company Profile, With Sources (`eliai/company-enrichment`) Actor

Turn a list of domains into company profiles: name, description, logo, on-domain emails, phone, address, social profiles and tech stack. Every field cites the URL it came from, so you can audit any row. No API keys, no data broker. $0.02 per domain; failed fetches never charged.

- **URL**: https://apify.com/eliai/company-enrichment.md
- **Developed by:** [Broke to Built](https://apify.com/eliai) (community)
- **Categories:** Lead generation, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $16.00 / 1,000 enriched domains

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 Enrichment — Domain to Company Profile, With Sources

**Turn a list of domains into company profiles — and every field tells you the URL it came from.**

Name, description, logo, on-domain emails, phone, postal address, social profiles, tech stack. No API
keys. No data broker. Everything is read from the company's own public website, so you can click the
source and check it.

***

### Why the sources matter

Most enrichment returns a confident row you cannot verify. When it is stale or wrong, you find out from
a bounced email or a prospect who left two years ago. Here every populated field looks like this:

```json
"name": {
  "value": "Apify",
  "source": "https://apify.com/",
  "how": "schema.org Organization name (JSON-LD)"
}
```

And a missing field is an honest `null` plus the `pagesRead` list — meaning *we looked at these pages
and it was not published there*, which is a different and more useful claim than silence.

### Input

```json
{ "domain": "stripe.com" }
```

Bulk — the normal case:

```json
{
  "domains": ["stripe.com", "apify.com", "vercel.com"],
  "followSubpages": true,
  "maxSubpages": 3
}
```

Bare domains, `www.`, and full URLs all work. Up to **200 domains per run**.

| Option | Default | What it does |
|---|---|---|
| `followSubpages` | `true` | Also read `/contact`, `/about`, `/impressum` style pages — where addresses and emails usually live. Much better coverage. |
| `maxSubpages` | `3` | How many extra pages per domain. |

### Output

```json
{
  "domain": "apify.com",
  "website": "https://apify.com/",
  "ok": true,
  "fieldsFound": 7,
  "pagesRead": ["https://apify.com/", "https://apify.com/about", "https://apify.com/contact"],
  "jsonLdOrganizationFound": true,
  "name": { "value": "Apify", "source": "https://apify.com/", "how": "schema.org Organization name (JSON-LD)" },
  "emails": { "value": ["support@apify.com", "hello@apify.com"], "source": "https://apify.com/contact", "how": "page text, filtered to the company domain" },
  "technologies": { "value": ["HubSpot", "Google Analytics", "Next.js", "Intercom"], "source": "https://apify.com/", "how": "signatures in the delivered HTML" },
  "social": { "linkedin": { "value": "https://www.linkedin.com/company/apify", "how": "schema.org sameAs (JSON-LD)" } },
  "phone": null,
  "address": null
}
```

### Pricing

| Event | Price |
|---|---|
| **Domain enriched** | **$0.02** |

**You are not charged for:** a domain whose site could not be fetched · an invalid domain · domains
skipped because the run timeout was approaching. One charge per domain no matter how many of its pages
we read.

1,000 domains = **$20**.

### FAQ

**Where does the data come from?**
The company's own website only: schema.org / JSON-LD `Organization` markup, OpenGraph and meta tags,
`mailto:`/`tel:` links, visible text on contact and about pages, and technology signatures in the
delivered HTML. Nothing is bought in, so nothing is silently years old.

**Why is `phone` or `address` sometimes null?**
Because the company did not publish it in a machine-readable place on the pages we read. We only claim
an address when it comes from structured `PostalAddress` markup — guessing one out of body text
produces confident nonsense, and a wrong address is worse than none. Check `pagesRead` to see exactly
where we looked.

**Are the emails real?**
They are the addresses published on the company's own site, filtered to that company's domain (so no
stray `someone@gmail.com` from a testimonial). They are role addresses like `support@` or `hello@`
more often than personal ones. This is not a personal-email finder and does not attempt to be.

**How is this different from the other enrichment actors?**
Provenance, and the absence of a data broker. You can audit any row in one click. If that does not
matter for your use case, a bulk broker feed may suit you better — we would rather say that than
pretend to be something else.

**Can it find employee counts or revenue?**
Only when the company publishes them as structured data (`numberOfEmployees`, `foundingDate`,
`vatID`/`taxID` are all read when present). Most do not. We do not estimate them.

**Does it respect the sites it reads?**
It fetches a small number of pages per domain with a normal timeout and an identifying user agent, and
it reads only what a browser would receive. It does not attempt logins, paywalls or bulk crawling.

### Limits, stated plainly

- **Public website data only** — no broker, no private records, no personal-email guessing.
- **Addresses require structured markup**; we will not infer one from prose.
- Phone numbers come from JSON-LD or `tel:` links only, for the same reason.
- Tech detection is signature-based on the delivered HTML: it is evidence of a signature, not an audit
  of a company's whole stack.
- Sites that block server-side requests, or render everything client-side with an empty initial HTML,
  will return few fields. The record says so rather than inventing them.

***

Built by [Broke to Built](https://broke2builtai.com) — a human-supervised AI team.
Questions: **eli@broke2builtai.com**, answered fast.

# Actor input Schema

## `domain` (type: `string`):

A company website, e.g. stripe.com. Bare domains, www. and full URLs all work. For a list, use the bulk field below — enrichment is priced per domain.

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

Paste your list. When you fill this, the single-domain field above is ignored — you are never charged for the demo domain.

## `followSubpages` (type: `boolean`):

Most companies publish addresses and emails on /contact, /about or /impressum rather than the homepage. Leave on for far better coverage; turn off for the fastest possible run.

## `maxSubpages` (type: `integer`):

How many contact/about style pages to read in addition to the homepage.

## Actor input object example

```json
{
  "domain": "apify.com",
  "domains": [],
  "followSubpages": true,
  "maxSubpages": 3
}
```

# Actor output Schema

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

One record per domain, every field with its source.

## `resultsCsv` (type: `string`):

The same companies as a spreadsheet-ready CSV.

# 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 = {
    "domain": "apify.com",
    "domains": []
};

// Run the Actor and wait for it to finish
const run = await client.actor("eliai/company-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 = {
    "domain": "apify.com",
    "domains": [],
}

# Run the Actor and wait for it to finish
run = client.actor("eliai/company-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 '{
  "domain": "apify.com",
  "domains": []
}' |
apify call eliai/company-enrichment --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,eliai/company-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/ut66X5xcYEAFe61B3/builds/TLgZ7RzEXJhWejaFU/openapi.json
