# Indian Company Data — CIN, Directors & Financials (`foxlabs/indian-company-data`) Actor

Look up any Indian company by CIN and get directors, financials, balance sheet, paid-up capital, charges & registry details as clean JSON. MCA-sourced data via Tofler — for due diligence, KYC, lead enrichment & investor research.

- **URL**: https://apify.com/foxlabs/indian-company-data.md
- **Developed by:** [Berkan Kaplan](https://apify.com/foxlabs) (community)
- **Categories:** Lead generation
- **Features:** Limited permissions
- **Stats:** 216 total users, 27 monthly users, 99.9% runs succeeded, 1 bookmarks
- **User rating**: No ratings yet

## Pricing

from $4.00 / 1,000 company records

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

## Indian Company Data — CIN, Directors & Financials 🇮🇳

**foXLabs India series:** [Government tenders](https://apify.com/foxlabs/india-government-tenders) · [NSE filings](https://apify.com/foxlabs/india-listed-company-filings) · [Tech hiring signals](https://apify.com/foxlabs/india-tech-hiring-signals) · [IndiaMART suppliers](https://apify.com/foxlabs/indiamart-supplier-data)

🎉 Turn Indian company filings into clean, structured company records — look companies up by CIN or name, or discover them by industry and state, and get directors with DIN, capital, balance sheet, charges, subsidiaries and locations as one row per company.
Built for due diligence, KYC / KYB, lead generation and investor research on Indian companies.

### 🔍 What is Indian Company Data — and when should you use it?

Give this Actor Indian **CINs** (the 21-character Corporate Identification Number), **company names** or **Tofler URLs** — or pick an **industry** and/or **state** to discover companies you don't know yet — and it returns one enriched record per company from the public company pages of [Tofler](https://www.tofler.in), which are compiled from **Ministry of Corporate Affairs (MCA)** filings. Every run reads the pages live.

**Use it when you need:** a company profile for KYC or vendor onboarding (status, class, registered office, directors with DIN); a lead list of Indian companies by sector and state; director, subsidiary and secured-loan (charge) networks for due diligence.

**Use something else when:** you need exact profit or net-worth rupee figures (Tofler keeps those in its paid tier — this Actor returns the public tier: revenue band plus year-on-year EBITDA and net-worth change), or personal phone numbers.

### 🤖 Use with AI agents

**Already on the Apify MCP server?** Ask for this Actor by name: `foxlabs/indian-company-data`.

**Your agent can pay for its own runs.** This Actor is pay-per-event with agentic payments, so an agent can discover it, run it and settle the bill over **x402 (USDC on Base)** or **Skyfire** — no Apify account or API token of its own. Billing is the same either way: per delivered company record — rows that only report a failed lookup are free from 25 September 2026.

Otherwise paste this into Claude, ChatGPT, Cursor or any MCP-enabled assistant:

```
I want Indian company records from the Apify Actor `foxlabs/indian-company-data`.
Input: `cins` is a list of 21-character CINs (exact match); `companyNames` is a list of company names (resolved by search, best-effort); or set `industry` and/or `state` to discover companies. `maxResults` caps the rows; `includeDirectorNetwork: true` adds every board seat of each director.
Start with: {"cins":["L17110MH1973PLC019786","L85110KA1981PLC013115"],"maxResults":10}
Ask me what to look up, run the Actor, then summarise the rows as a table.
```

The machine-readable API, MCP config and OpenAPI definition live at `apify.com/foxlabs/indian-company-data.md`.

### 📋 Overview

Everything you need to turn Indian company filings into structured data — in one Actor, with no login, cookies or API key.

**Why teams pick this Actor:**

- ✅ **Look up or discover** — exact CIN lookup, name lookup, or a lead list by industry × state (30 industries × 36 states and union territories).
- 🧑‍💼 **Directors with DIN** — and, on request, every other company each director sits on.
- 🏦 **Capital, balance sheet and charges** — paid-up and authorised capital, latest balance-sheet items, secured borrowings.
- 🌐 **Subsidiaries and locations** — subsidiary list plus registered office, branches, factories and warehouses with coordinates.
- 💰 **Pay per record** — $0.004 per company record, no subscription.
- 🤖 **Agent-ready** — MCP + x402 agentic payments.

### ✨ Features

- 🔍 **Three ways in** — `cins` (exact), `companyNames` (resolved by search), `companyUrls` (Tofler company URLs).
- 🧭 **Discovery** — `industry` and/or `state` walk Tofler's public company directory and enrich every company found.
- 🧹 **Filters** — keep one status (`Active`, `Strike Off`, `Dissolved`, …) or one class (public, private, one person).
- 🕸️ **Director network** — `includeDirectorNetwork` fetches each director's board seats (`maxDirectorsPerCompany`, default 25).
- 🧾 **Clean values** — capital as numeric ₹ Cr next to the readable text, placeholder dashes turned into `null`, ISO dates inside the director network.

### 🎬 Quick Start

```bash
curl -X POST "https://api.apify.com/v2/acts/foxlabs~indian-company-data/runs?token=YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"cins":["L17110MH1973PLC019786","L85110KA1981PLC013115"],"maxResults":10}'
```

### 🚀 Getting Started (3 steps)

1. **Choose your targets** — CINs for exact matches, names for convenience, or an industry and state to discover companies.
2. **Set the cap** — `maxResults` limits how many companies come back (default 100; 0 = no limit).
3. **Run and export** — download the dataset as JSON, CSV, Excel, HTML or XML.

### 📥 Input

```json
{"cins":["L17110MH1973PLC019786","L85110KA1981PLC013115"],"maxResults":100}
```

| Field | Type | Description |
|---|---|---|
| `cins` | array | 21-character CINs, one per line — exact match. |
| `companyNames` | array | Company names, resolved to a CIN by search (best-effort — check `name` in the output). |
| `companyUrls` | array | Full Tofler company URLs, or a .txt / .csv upload. |
| `excludeCins` | array | CINs you already have, one per line. Any company with a CIN in this list is skipped — not fetched, not returned, and not charged. Pass the CINs from a previous run to paginate discovery and get only new companies. |
| `industry` | string | Discover companies in one of 30 sectors, e.g. `computer-related-services`, `manufacturing-textiles`. |
| `state` | string | Discover companies registered in one of 36 states / UTs (e.g. `karnataka`), or filter look-ups to it. |
| `statusFilter` | string | Keep one status: `Active`, `Strike Off`, `Dissolved`, `Under Liquidation`, `Dormant`, `Not Available for eFiling`. |
| `companyClassFilter` | string | Keep one class: `public`, `private`, `one person`. |
| `maxResults` | integer | Exact cap on companies returned and charged (default 100; 0 = unlimited). In discovery mode it is also how many companies are pulled from the directory. |
| `includeDirectorNetwork` | boolean | For every director, also fetch every company they sit on — one extra page per director. Default off. |
| `maxDirectorsPerCompany` | integer | Director network only — how many directors per company get their board seats fetched (default 25, max 100). |
| `maxConcurrency` | integer | Companies fetched in parallel (default 10). |
| `proxyConfiguration` | object | Apify proxy settings (default: Apify proxy, automatic selection). |

**More recipes**

- Lead list: `{"industry":"computer-related-services","state":"karnataka","maxResults":50}` — 50 IT companies registered in Karnataka, each fully enriched (≈ $0.20).
- Watch-list screen: `{"companyNames":["Infosys","Reliance Industries"],"statusFilter":"Active","companyClassFilter":"public","maxResults":20}` — resolves each name, keeps only active public companies.
- Director network: `{"cins":["L85110KA1981PLC013115"],"includeDirectorNetwork":true,"maxResults":1}` — Infosys' directors, each with every company they sit on.
- Paginate discovery across runs: run `{"industry":"computer-related-services","state":"karnataka","maxResults":100}`, collect the `cin` values, then on the next run add `"excludeCins":[…those CINs…]` to get only new companies.

### 📤 Output

One row per company. A lookup that fails still writes a row with an `error` field (and `matched: false` when a name could not be resolved), so nothing disappears silently. From 25 September 2026 these rows are not charged.

| Field | Description |
|---|---|
| `cin` / `pan` | Corporate Identification Number and PAN |
| `name` / `status` / `companyClass` | Legal name, status (Active / Strike Off …), public / private class |
| `incorporationDate` / `incorporationYear` / `ageYears` | Incorporation date, year and age in years |
| `description` | One-line business description (`null` when the page has none) |
| `registeredAddress` / `registeredState` / `registeredPincode` | Registered office |
| `paidUpCapital` / `paidUpCapitalCr` / `authorisedCapital` / `authorisedCapitalCr` / `currency` | Capital — readable text and numeric ₹ Cr |
| `operatingRevenueRange` / `revenueFyEnd` | Public revenue band and financial-year end |
| `ebitdaChangePct` / `networthChangePct` | Year-on-year change, % |
| `agm` / `lastAgmDate` / `email` | Last AGM and the registered email on the filings |
| `directors[]` / `directorsCount` / `directorsText` | Board — name, designation, DIN, tenure, `profileUrl`; with Director network on also `directorships[]` (company, CIN, status, industry, incorporation date, appointment date, designation) and `directorshipsCount` |
| `directorNetworkRequested` / `directorNetworkCount` | Director network only — flag and number of distinct other companies reached through the board |
| `balanceSheet` / `balanceSheetText` | Latest-year balance-sheet items (₹ Cr) |
| `charges[]` / `chargesCount` / `chargesText` | Secured borrowings — holder, amount, date |
| `subsidiaries[]` / `subsidiariesCount` / `subsidiariesText` | Subsidiaries — name, incorporation year, location, paid-up capital, link (up to 200 per company; the count is always the full total) |
| `locations[]` / `locationsCount` | Registered office, branches, factories, warehouses with coordinates (up to 100 per company; the count is always the full total) |
| `query` / `nameMatchScore` | Name look-ups only — the name you searched and the share of its words found in the resolved legal name (1 = all; 0 = none, returned as a free `error` row with `candidateName` / `candidateCin`); `null` for CIN, URL and discovery rows |
| `url` / `matched` / `source` / `scrapedAt` | Source page, match flag, source name, timestamp |

Sample — Reliance Industries, captured 2026-09-10 with Director network on (lists trimmed to one entry):

```json
{
  "url": "https://www.tofler.in/company/L17110MH1973PLC019786",
  "cin": "L17110MH1973PLC019786",
  "name": "RELIANCE INDUSTRIES LIMITED",
  "status": "Active",
  "companyClass": "public limited company",
  "pan": null,
  "incorporationDate": "08 May, 1973",
  "incorporationYear": 1973,
  "ageYears": 53.3,
  "description": "The company is engaged in Exploration & Production, Petroleum Refining & Marketing, Retail Investor Relations, Petrochemicals, Textiles, Retail and mobile network operations",
  "registeredAddress": "3 RD FLOORMAKER CHAMBER IV 222 NARIMAN POINT",
  "registeredState": "Maharashtra",
  "registeredPincode": "400021",
  "paidUpCapital": "₹ 13,532.5 Cr",
  "paidUpCapitalCr": 13532.5,
  "authorisedCapital": "₹ 50,000.0 Cr",
  "operatingRevenueRange": "Over INR 500 cr",
  "revenueFyEnd": "31 March, 2025",
  "ebitdaChangePct": -21.81,
  "networthChangePct": 5.43,
  "lastAgmDate": "19 June, 2026",
  "directorsCount": 14,
  "directors": [
    {
      "designation": "Whole-time Director",
      "name": "Hital Rasiklal Meswani",
      "din": "00001623",
      "tenure": "16 years",
      "profileUrl": "https://www.tofler.in/hital-rasiklal-meswani/director/00001623",
      "directorships": [
        {
          "companyName": "THE INDIAN FILM COMBINE PVT LTD",
          "cin": "U92100MH1942PTC003702",
          "companyUrl": "https://www.tofler.in/the-indian-film-combine-pvt-ltd/company/U92100MH1942PTC003702",
          "incorporationDate": "1942-10-19",
          "industry": "Recreational, cultural and sporting activities",
          "status": "Active",
          "appointedOn": "2018-07-23",
          "asOn": "2025-07-16",
          "designation": "Director"
        }
      ],
      "directorshipsCount": 5
    }
  ],
  "directorNetworkRequested": true,
  "directorNetworkCount": 48,
  "balanceSheet": {
    "period": "Mar 2025",
    "currency": "INR (₹ Cr)",
    "items": {
      "Equity Capital": 13532,
      "Reserves": 996094,
      "Borrowings +": 347530,
      "Long term borrowings": 236899
    }
  },
  "chargesCount": 0,
  "charges": [],
  "subsidiariesCount": 291,
  "subsidiaries": [
    {
      "name": "Reliance Digital Health USA Inc.",
      "incorporation": null,
      "location": "Usa",
      "paidUpCapital": null,
      "url": null
    }
  ],
  "locationsCount": 312,
  "locations": [
    {
      "address": "3 RD FLOORMAKER CHAMBER IV 222 NARIMAN POINT",
      "type": "Registered Office",
      "state": "Maharashtra",
      "pincode": "400021",
      "lat": 19.0759837,
      "lng": 72.8776559
    }
  ],
  "matched": true,
  "source": "tofler.in",
  "scrapedAt": "2026-09-10T11:29:40.686Z"
}
```

### 💼 Use cases

**1. KYC and vendor onboarding** — verify an Indian company before you sign.
*Input:* its CIN. *Output:* status, class, registered office, directors with DIN, charges. *Use:* confirm the entity exists, is Active and who runs it.

**2. B2B lead lists by sector and state** — no names needed.
*Input:* an industry and a state. *Output:* enriched companies with capital and revenue bands. *Use:* a ready prospect list.

**3. Due diligence and conflict-of-interest checks** — see who else the board controls.
*Input:* a CIN with `includeDirectorNetwork: true`. *Output:* every board seat of every director. *Use:* spot related parties and shared directors.

**4. Credit and risk screening** — secured borrowings and financial direction.
*Input:* a list of CINs. *Output:* charges, balance sheet, year-on-year EBITDA and net-worth change. *Use:* flag leveraged or shrinking counterparties.

### 🔗 Integration

**JavaScript / Node.js**

```javascript
import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: 'YOUR_TOKEN' });
const run = await client.actor('foxlabs/indian-company-data').call({"cins":["L17110MH1973PLC019786"],"maxResults":10});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items[0]);
```

**Python**

```python
from apify_client import ApifyClient
client = ApifyClient('YOUR_TOKEN')
run = client.actor('foxlabs/indian-company-data').call(run_input={"cins": ["L17110MH1973PLC019786"], "maxResults": 10})
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)
```

Written for `apify-client` 3 for Python, where `call()` returns a run object; with version 1 or 2 it returns a dict — write `run['defaultDatasetId']` there.

**Automation (n8n / Zapier / Make):** schedule or webhook → HTTP request to the Actor API with your `cins` → handle the JSON dataset → push to a sheet, CRM or dashboard.

### 📊 Pricing

Pay-per-event: **$0.004 per delivered company record** (≈ $4 per 1,000 companies), plus Apify's run-start event ($0.00005 per GB of run memory). Director network fetches more pages but costs the same per company. **From 25 September 2026, rows that only report a failed lookup (`error`) are free.** Until then Apify still counts them as dataset items. [Current pricing](https://apify.com/foxlabs/indian-company-data).

**Spending limit.** Before every record the Actor checks the run's maximum charge — the limit you set for the run, or else what is left of your monthly usage limit. When there is no room for another record it stops fetching, keeps what it has delivered, and the status message says how many companies you got.

### ❓ FAQ

#### How is billing calculated?

Pay per result: you are charged only for company records actually returned, never for an empty run or an error.

#### Is it legal to use this data?

It reads official, publicly published Indian company-registry data. It collects no private personal data beyond what the registry publishes, and requires no login. Use the output in line with applicable laws.

#### Where does the data come from?

From Tofler's public company pages, which compile Ministry of Corporate Affairs (MCA) filings. The Actor reads the public tier only — no login and no paid account.

#### CIN or name?

A CIN is exact. A name is resolved by web search and can land on a similarly named company — check `name` and `nameMatchScore` in the output, or use the CIN. A score of 0 means no word of your name is in the legal name: that row comes back free, as an `error` row naming the candidate (`candidateName`, `candidateCin`) — usually a different company, sometimes a brand whose registered legal name is different; query the CIN if it is the one you meant. A score of 1 can still be a group company that carries the brand in its name — in our test, searching `Byju's` returned BYJU'S K3 EDUCATION PRIVATE LIMITED — so use the CIN when the exact entity matters.

#### How does discovery work?

Pick an `industry` and/or `state`; the Actor walks Tofler's public company directory page by page up to `maxResults` and enriches every company it finds.

#### What does Director network add?

For each director (up to `maxDirectorsPerCompany`), every company they sit on — company, CIN, status, industry, incorporation date, appointment date and designation. Measured on Infosys + Reliance: 22 directors → 127 board seats (run `gBJT7xLtc5EctFXnI`).

#### Why are exact profit figures missing?

Tofler keeps exact profit and net-worth numbers in its paid tier. You get the public revenue band and the year-on-year EBITDA and net-worth change.

#### Can I export to CSV / Excel / JSON?

Yes — directly from the Apify dataset.

### 🐛 Troubleshooting

- **A name returns the wrong company** — look at `nameMatchScore` (low = likely mismatch) and use the CIN instead; names are resolved by search.
- **Rows with `matched: false` or `error`** — the name could not be resolved or the page returned an error; check the spelling or use the CIN.
- **The run takes long** — Director network adds one page per director; lower `maxDirectorsPerCompany` or switch it off.
- **Discovery returns fewer rows than `maxResults`** — that industry × state combination has fewer companies in the directory.
- **The run ended with "stopped because the maximum charge … was reached"** — the run's maximum charge, or what is left of your monthly usage limit, covered fewer companies than you asked for. The dataset holds the ones that were delivered; raise the limit and run the rest.

### ⚖️ Is it legal to scrape this data?

The Actor reads publicly accessible company pages; the underlying information is statutory MCA filing data. Director names and DINs are personal data under India's Digital Personal Data Protection Act, 2023 — process them only for a lawful purpose such as KYC or due diligence, and check that your use fits the source website's terms. Tofler is a trademark of its owner; this Actor is not affiliated with Tofler or the MCA.

### 🤝 Support & contact

- 🌐 **Website:** [data.foxlabs.com.tr](https://data.foxlabs.com.tr)
- 📧 **Email:** info@foxlabs.com.tr
- 🐛 **Issues:** open a ticket in the Actor’s **Issues** tab
- 🧰 **More clean B2B data actors:** [Fox Labs on Apify](https://apify.com/foxlabs)

### Changelog

#### 0.2.30 — 2026-11-13 — in-memory crawl queue & faster short runs

- Crawl queue and session state now run in memory with dataset-backed resume deduplication, speeding up short CIN lookups and discovery runs. No output field or pricing change.

#### 0.2.26 — 2026-10-23 — `excludeCins` to skip companies you already have + exact `maxResults` cap

- New input **`excludeCins`** (array of CINs): any company whose CIN is in the list is skipped — not fetched, not returned, and not charged. Pass the CINs from a previous run to paginate discovery and reach only new companies.
- **`maxResults` is now an exact cap** on delivered and charged companies — setting it to 100 returns 100, not 110 (concurrent in-flight pages can no longer slip past the limit).
- No change to output fields or pricing.

#### 0.2.25 — 2026-10-08 — README: the Python example works with the current Apify client

- The README's Python example read the results with `run['defaultDatasetId']`. With the current Apify client for Python (version 3) `call()` returns a run object, not a dict, and that line raised `TypeError: 'Run' object is not subscriptable` — after the run itself had finished. The example now reads `run.default_dataset_id`; with client version 1 or 2, keep `run['defaultDatasetId']`. Checked with apify-client 3.2.1, 2.5.1 and 1.12.2.
- No code, output field or pricing change.

#### 0.3.4 — 2026-10-07 — the run stops at its maximum charge and says so

- **A run that reaches its maximum charge now stops by itself and tells you.** The maximum charge is the limit you set for the run, or else what is left of your monthly usage limit. Until now the Actor did not look at it: companies past the limit were logged as pushed but left out of the dataset, and a longer run was aborted by Apify. The Actor now checks the room left before every record, stops fetching when there is none, and finishes as a normal run with a status message that says how many companies were delivered. Nothing past the limit is charged.
- **`maxResults` is a hard cap with the director network on, too.** 3 CINs with `maxResults: 1` and `includeDirectorNetwork` returned 3 records; they now return 1.
- No output field changed, no pricing change.

#### 0.3.3 — 2026-09-26 — a name that matches nothing is no longer charged

- A name look-up whose result shares no word with the searched name now comes back as a **free** row with `error`, `candidateName`, `candidateCin` and `nameMatchScore: 0`, instead of a charged company record. If the candidate is the company you meant (a brand whose legal name differs, such as CRED → Dreamplug Technologies), query its CIN.

#### 0.3.2 — 2026-09-10 — failed lookups become free (per-record billing)

- **You will pay only for delivered company records.** The Actor now charges a new `company-record` event for each delivered company, and rows that only report a failed lookup (`error`, `matched: false`) are pushed without a charge.
- **Timing:** Apify applies pricing changes after a 14-day notice. From **25 September 2026** the pricing switches from the per-dataset-item event to `company-record` at the same price ($0.004). Until then billing is exactly as before; the code detects the switch by itself.
- No output field changed.

#### 0.3.1 — 2026-09-10 — name-match check, README + dataset schema

- **New fields for name look-ups: `query` and `nameMatchScore`.** Names are resolved through web search, and a vague or unknown name could come back as an unrelated company with nothing in the row to show it. Rows from `companyNames` now carry the searched name and the share of its words found in the resolved legal name (1 = all, 0 = none; legal suffixes ignored). Both are `null` for CIN, URL and discovery rows. Additive — no existing field changed, no row is dropped.
- README rebuilt to the current Fox Labs standard (AI agents / MCP / x402, use cases, integration, FAQ, troubleshooting, legal, support) with this Actor's real inputs: `cins`, `companyNames`, `companyUrls`, `industry`, `state`, the status / class filters and Director network. The 2026-09-07 README showed a placeholder input (`queries`) that this Actor does not read.
- Typed dataset schema restored (the 0.3 build shipped without it) and extended with the Director network fields and the two new fields.

#### 0.3 — 2026-09-10 — Director network

- **New input `includeDirectorNetwork` (default off) + `maxDirectorsPerCompany` (default 25).** For every director the Actor fetches their Tofler director page (`/<slug>/director/<DIN>`) and attaches `directorships[]` — company name, CIN, company URL, status, industry, incorporation date, appointment date, "as on" date, designation — plus `directorshipsCount`. The company row gets `directorNetworkRequested` and `directorNetworkCount` (distinct other CINs across the board).
- **`directors[].profileUrl`** is now always emitted (link to the director page).
- Measured locally 2026-09-10 (Infosys + Reliance, 24 requests, 0 failed): 22 directors → 127 board seats; fill: companyName/cin/companyUrl/incorporationDate/status/appointedOn/asOn/designation 127/127, industry 124/127; uniqueness DIN+CIN 127/127; 96/127 seats have an "as on" date in 2025–2026.
- Additive change: no existing field renamed or removed. Dates in `directorships[]` are ISO (YYYY-MM-DD).
- A failed director page never drops the company: the director gets `directorships: null` + `directorNetworkError` and the company row still ships.

#### 0.2.1 — 2026-07-28

- **`age` split into typed fields.** Tofler renders one string, `"1981, 45.1 years"`, and the Actor shipped it verbatim as `age` — while `incorporationYear` (1981) already carried the year half. `age` is replaced by numeric **`ageYears`** (`45.1`); `incorporationYear` is unchanged. Measured on 30 live company pages: `age` filled 30/30 before → `ageYears` filled 30/30 after, `incorporationYear` 30/30 in both.
- **Masked empties are `null`, not placeholder text.** Tofler writes `"-"` where it has no figure and `"NA"` / `"0"` where it has no address detail, and those placeholders were reaching the dataset as values. A single `unmask()` helper now maps them to `null`. Measured over the same 30 pages: `balanceSheet.items` **26 of 374 cells** were the string `"-"` (12 of 30 companies affected) → 0, now `null`; `pan` **7 of 30** was `"-"` → 0; `locations[]` 3 cells (`address:"NA"`, `pincode:"NA"`, `type:"0"`) → 0. Whole-record scan for masked empties: **35 → 0**. Numeric balance-sheet values, `balanceSheetText` and every other field are unchanged.
- **`description` is the company's business description, not Tofler's ad copy.** The field was `meta[name="description"]`, i.e. Tofler's SEO line — *"Are you looking for Infosys Limited financials? Visit Tofler for its net worth, ratios…"* — identical boilerplate on 30 of 30 companies and of no value to a buyer. It now carries the one-line business description Tofler prints above the company paragraph (*"The company manufactures and refines sugar in India and internationally"*). Measured: **17 of 30** companies have one and now return it, 0 boilerplate leaked, 0 clipped; the other 13 pages carry no description at all and return `null` rather than filler.
- Unchanged and re-verified on the same run: CIN, PAN (where present), status, company class, email, `directors[]` with DIN, balance-sheet figures, charges, subsidiaries, locations and geo-coordinates.

#### 0.2 — 2026-07-17

- Discovery mode: browse companies by industry + state (30 industries × 36 states) and enrich every match.
- Prefilled example CINs (Reliance, Infosys) so the first run returns full profiles with no setup.

#### 0.1

- Initial release. CIN / company-name / Tofler-URL lookup: identity, status, capital, directors with DIN, latest balance sheet, charges, subsidiaries and locations.

# Changelog

This Actor's version history is a separate document: https://apify.com/foxlabs/indian-company-data/changelog.md

# Actor input Schema

## `companyNames` (type: `array`):

Type Indian company names — one per line (e.g. `Infosys`, `Reliance Industries`). Each is resolved to its company profile via search. ⚠ Best-effort: a shared/ambiguous name may resolve to the wrong company — for guaranteed results use the CIN below. Always check the `matched` field + returned name.

## `cins` (type: `array`):

One CIN per line — e.g. `L17110MH1973PLC019786`. The CIN is the 21-character MCA identifier on every Indian company's filings. No ambiguity — exact match.

## `companyUrls` (type: `array`):

Full Tofler URLs, e.g. `https://www.tofler.in/company/L17110MH1973PLC019786`, or upload a .txt/.csv.

## `excludeCins` (type: `array`):

One CIN per line. Any company with a CIN in this list is skipped — not fetched, not returned, and NOT charged. Use it to paginate discovery across runs: pass the CINs you already collected and each new run returns only NEW companies.

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

DISCOVER companies by sector — no names needed. Combine with State below to narrow (e.g. Computer & IT services + Karnataka = Bangalore tech companies). Each match is fully enriched with directors, financials & charges.

## `state` (type: `string`):

DISCOVER companies registered in this state (or filter look-ups to it). Combine with Industry above for a precise list.

## `statusFilter` (type: `string`):

Keep only companies with this status (applied after enrichment). Leave empty for all.

## `companyClassFilter` (type: `string`):

Keep only companies of this class.

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

Hard cap on results — pay-per-result pricing scales linearly. In discovery mode this is also how many companies are pulled from the browse list. Set 0 for unlimited.

## `includeDirectorNetwork` (type: `boolean`):

For every director, also fetch the list of all companies they sit on: company name, CIN, status, appointment date and designation. Adds one request per director, so runs take longer. Leave off unless you need the network.

## `maxDirectorsPerCompany` (type: `integer`):

Only used when Director network is on. Caps how many directors per company get their board seats fetched. Default 25.

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

How many companies to fetch in parallel. Default 10 is balanced.

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

Apify Datacenter proxy is sufficient.

## Actor input object example

```json
{
  "companyNames": [],
  "cins": [
    "L17110MH1973PLC019786",
    "L85110KA1981PLC013115"
  ],
  "companyUrls": [],
  "excludeCins": [],
  "industry": "",
  "state": "",
  "statusFilter": "",
  "companyClassFilter": "",
  "maxResults": 100,
  "includeDirectorNetwork": false,
  "maxDirectorsPerCompany": 25,
  "maxConcurrency": 10,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `dataset` (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 = {
    "companyNames": [],
    "cins": [
        "L17110MH1973PLC019786",
        "L85110KA1981PLC013115"
    ],
    "companyUrls": [],
    "excludeCins": [],
    "industry": "",
    "state": "",
    "maxResults": 100,
    "maxConcurrency": 10
};

// Run the Actor and wait for it to finish
const run = await client.actor("foxlabs/indian-company-data").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 = {
    "companyNames": [],
    "cins": [
        "L17110MH1973PLC019786",
        "L85110KA1981PLC013115",
    ],
    "companyUrls": [],
    "excludeCins": [],
    "industry": "",
    "state": "",
    "maxResults": 100,
    "maxConcurrency": 10,
}

# Run the Actor and wait for it to finish
run = client.actor("foxlabs/indian-company-data").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 '{
  "companyNames": [],
  "cins": [
    "L17110MH1973PLC019786",
    "L85110KA1981PLC013115"
  ],
  "companyUrls": [],
  "excludeCins": [],
  "industry": "",
  "state": "",
  "maxResults": 100,
  "maxConcurrency": 10
}' |
apify call foxlabs/indian-company-data --silent --output-dataset

```

## MCP server setup

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

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/3pXp7Obhm7MEHRe4c/builds/g02aiNAeLh4KFVawM/openapi.json
