# Website Visitor Identification API - IP to Company (`nabeelbaghoor/website-visitor-identification-api`) Actor

Resolve anonymous website visitor IP addresses to companies, or enrich domains and work emails into firmographics: industry, employee and revenue ranges, SIC and NAICS codes, location, predictive scores and segments. Pay per match. Bring your own API key.

- **URL**: https://apify.com/nabeelbaghoor/website-visitor-identification-api.md
- **Developed by:** [Nabeel Hassan](https://apify.com/nabeelbaghoor) (community)
- **Categories:** Business, Developer tools, Lead generation
- **Stats:** 2 total users, 1 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$15.00 / 1,000 company results

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/platform/actors/running/actors-in-store#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

## Website Visitor Identification API - IP to Company

Turn anonymous website traffic into named accounts. Paste a list of visitor IP addresses and get the company behind each one, complete with industry, employee and revenue ranges, SIC and NAICS codes, headquarters location, and, where your account publishes them, predictive intent scores, buying stage and segment membership. The same actor also works the other way round: give it company domains or work email addresses and it returns the same firmographic record. You pay only for the inputs that resolve to a company.

This actor is built for web deanonymisation, routing inbound leads, enriching form fills from a work email, and attaching firmographics to server logs or analytics exports.

### What you can do with it

- Identify which companies visited your website from a list of server or analytics IP addresses.
- Score and route inbound traffic by company size, revenue and industry before a form is ever filled in.
- Enrich a signup or demo request list from nothing but a work email address.
- Attach SIC and NAICS codes to an account list for territory or segment planning.
- Pull buying stage and intent scores alongside the firmographics for accounts in your published segments.
- Export everything as JSON, CSV or Excel, or push it into your CRM or warehouse.

### Features

- Two modes in one actor: identify by visitor IP, or enrich by domain or work email address.
- IPv4 and IPv6 are both accepted, and malformed entries are dropped before any call is made.
- Optional visitor cookie and custom tracking id headers are forwarded when you captured them on your own site.
- Optional context hints on enrichment lookups, including country, company name, industry, job title and role, to sharpen the match.
- Predictive scores are kept as a full array and also flattened into top product, buying stage, profile fit, intent score and the qualified-account flag.
- Segment membership is normalised into clean id and name arrays whichever shape your account's API settings return.
- Unmatched inputs are kept as placeholder rows so your output lines up with your input, and are never charged. Turn on `skipUnmatched` to drop them instead.
- The complete raw provider payload is kept on every record, so nothing is lost.
- Rate limits are handled with retry-after aware backoff, and a run that hits a limit keeps everything already collected.
- Pay-per-result pricing with a hard result cap so a run can never surprise you.

### Input

| Field | Type | Description |
| --- | --- | --- |
| `lookupMode` | string | `identify` for IP addresses, `enrich` for domains and emails. |
| `ipAddresses` | array | Identify: visitor IP addresses, one per line. |
| `epsilonCookie` | string | Identify: the provider's visitor cookie value. Optional. |
| `customId` | string | Identify: your own tracking identifier. Optional. |
| `domains` | array | Enrich: company domains, one per line. |
| `emails` | array | Enrich: work email addresses, one per line. |
| `country`, `company`, `industry`, `title`, `role`, `firstname`, `lastname`, `leadsource` | string | Enrich: optional context hints. |
| `skipUnmatched` | boolean | Drop unmatched inputs instead of storing a placeholder. |
| `maxResults` | integer | Stop after this many rows (1 to 10,000). |
| `apiKey` | string | Your API token. Required, stored securely. |

### Example output

Each dataset item is one input. Fields are populated where the provider has data, and the complete provider payload is kept under `raw`:

```json
{
  "queriedIp": "8.8.8.8",
  "matched": true,
  "companyMatch": "Matched",
  "confidence": "High",
  "companyId": "1234567",
  "name": "Example Manufacturing",
  "domain": "example.com",
  "industry": "Manufacturing",
  "subIndustry": "Industrial Machinery",
  "employeeRange": "1,000 - 4,999",
  "employeeCount": 2400,
  "revenueRange": "$500M - $1B",
  "annualRevenue": 720000000,
  "sic": "3559",
  "naics": "333249",
  "address": "1 Industrial Way",
  "city": "Columbus",
  "state": "Ohio",
  "stateCode": "OH",
  "zip": "43004",
  "country": "United States",
  "countryIsoCode": "US",
  "region": "North America",
  "scores": [
    {
      "product_name": "Warehouse Automation",
      "buying_stage": "Decision",
      "profile_fit": "Strong",
      "intent_score": 87,
      "is_6qa": true
    }
  ],
  "topProduct": "Warehouse Automation",
  "buyingStage": "Decision",
  "profileFit": "Strong",
  "intentScore": 87,
  "is6qa": true,
  "segmentIds": ["4471"],
  "segmentNames": ["Enterprise Manufacturing NA"],
  "raw": { "company": { "name": "Example Manufacturing" } }
}
```

An input with no company match is stored as `{ "queriedIp": "…", "matched": false }` unless you switch `skipUnmatched` on.

### Pricing and the credit model

This actor uses pay-per-result pricing. You are charged a fixed price for each input that resolved to a company. Unmatched inputs are stored free of charge, and a run that matches nothing costs nothing. Set `maxResults` to cap how many rows a run can collect, and set a run spending limit as a second safety net. Your own provider plan meters its own API calls separately.

### Frequently asked questions

#### What data does this actor return?

The matched company's name and domain, industry and sub industry, employee count and range, annual revenue and revenue range, SIC and NAICS codes, the full address broken into street, city, state, postal code, country and region, a match confidence, plus predictive scores with buying stage, profile fit, intent score and the qualified-account flag, and segment membership as ids and names. Every record also carries the untouched provider payload.

#### Why do some IP addresses return no company?

Residential broadband, mobile carrier and VPN addresses generally cannot be attributed to a business, and small companies may not be in the index at all. Those inputs come back as `matched: false` and are not charged. Realistic match rates on real website traffic are well below 100 percent, which is normal for IP-based identification.

#### Do I get intent scores and segments?

Only if your provider account has them. Scores and segments are controlled by your own API settings on the provider side, and segments must be published there before they appear in an API response. If neither is enabled, the firmographic fields still come back and the score and segment fields are simply empty.

#### Can I look a company up by domain instead of an IP?

Yes. Switch `lookupMode` to `enrich` and supply `domains`, `emails`, or both. That path calls the provider's firmographics endpoint and returns the same row shape, which makes it easy to combine an IP run and a domain run in one dataset.

#### Do work email addresses work as input?

Yes, in enrich mode. A work address such as `jane@example.com` is resolved to its company. Free mailbox providers such as Gmail or Outlook normally return no match, since the domain does not identify an employer.

#### What are the context hints for?

`country`, `company`, `industry`, `title`, `role`, `firstname`, `lastname` and `leadsource` are optional fields the enrichment endpoint accepts alongside the domain or email. They give the provider extra signal for disambiguating a match and are passed straight through.

#### How does the actor handle rate limits?

It throttles requests, honours the retry-after signal on a rate-limited response, and backs off exponentially. If the limit is still in force it stops early and keeps everything already collected rather than failing the whole run.

#### How am I charged?

You pay a fixed price per matched company returned to the dataset. Unmatched inputs and empty runs cost nothing. Use `maxResults` and the run spending limit to control cost.

#### How do I get an API token?

The API is part of a paid platform package. Ask your provider administrator to issue an API token from the platform's API settings, where scores and segment visibility are configured at the same time. Paste the token into `apiKey`.

#### What output formats are available?

The dataset can be exported as JSON, CSV, Excel, HTML or RSS, or read through the API for pushing into a CRM or warehouse.

### Bring your own API key

This actor connects to a third-party company identification provider (6sense) on your behalf and requires your own provider API token. It is stored securely and never logged, and the actor never ships with or shares credentials.

### Keyword map

website visitor identification api, ip to company api, company identification api, web deanonymization, anonymous visitor tracking, reverse ip lookup company, firmographic enrichment api, account identification, abm data api, buyer intent data, buying stage data, company segment membership, employee range data, revenue range data, sic naics lookup, work email to company, inbound lead routing, website traffic to accounts, b2b visitor analytics, ip address company lookup.

# Actor input Schema

## `lookupMode` (type: `string`):

`Identify` resolves anonymous website visitor IP addresses to companies. `Enrich` resolves company domains or work email addresses to the same firmographic record.

## `ipAddresses` (type: `array`):

Identify mode. The visitor IP addresses to resolve, one per line. IPv4 and IPv6 are both accepted. Duplicates and malformed entries are dropped.

## `epsilonCookie` (type: `string`):

Optional. The provider's visitor tracking cookie value, forwarded with the request to improve the match when you captured it on your own site.

## `customId` (type: `string`):

Optional. Your own identifier, forwarded with the request so the provider can tie the call back to your session or campaign.

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

Enrich mode. Company domains to resolve, one per line, for example `example.com`. Full URLs are accepted and reduced to their domain.

## `emails` (type: `array`):

Work email addresses to resolve to their company, one per line. Free mailbox providers usually return no match.

## `country` (type: `string`):

Optional context sent with an enrichment lookup to help disambiguate the match.

## `company` (type: `string`):

Optional company name sent with an enrichment lookup as an extra matching signal.

## `industry` (type: `string`):

Optional industry sent with an enrichment lookup.

## `title` (type: `string`):

Optional job title of the person the email belongs to.

## `role` (type: `string`):

Optional role of the person the email belongs to.

## `firstname` (type: `string`):

Optional first name of the person the email belongs to.

## `lastname` (type: `string`):

Optional last name of the person the email belongs to.

## `leadsource` (type: `string`):

Optional label for where the lead came from, passed through to the provider for its own reporting.

## `skipUnmatched` (type: `boolean`):

When enabled, inputs the provider cannot resolve to a company are left out of the dataset entirely. When off, they are stored as a placeholder row with `matched: false` so the output lines up with your input list. Unmatched rows are never charged either way.

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

Stop after this many rows (1-10,000). One row is one IP address, domain or email. You are charged only for rows that resolved to a company.

## `apiKey` (type: `string`):

Your own API token for the data provider. Required. It is issued in the provider's platform. Stored securely here and never logged.

## Actor input object example

```json
{
  "lookupMode": "identify",
  "ipAddresses": [
    "8.8.8.8"
  ],
  "domains": [],
  "emails": [],
  "skipUnmatched": false,
  "maxResults": 100
}
```

# 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 = {
    "ipAddresses": [
        "8.8.8.8"
    ],
    "domains": [],
    "emails": [],
    "maxResults": 100
};

// Run the Actor and wait for it to finish
const run = await client.actor("nabeelbaghoor/website-visitor-identification-api").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 = {
    "ipAddresses": ["8.8.8.8"],
    "domains": [],
    "emails": [],
    "maxResults": 100,
}

# Run the Actor and wait for it to finish
run = client.actor("nabeelbaghoor/website-visitor-identification-api").call(run_input=run_input)

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

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

```

## CLI example

```bash
echo '{
  "ipAddresses": [
    "8.8.8.8"
  ],
  "domains": [],
  "emails": [],
  "maxResults": 100
}' |
apify call nabeelbaghoor/website-visitor-identification-api --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=nabeelbaghoor/website-visitor-identification-api",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

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