# Enriching Tables

> Enrich any CSV of companies or people with web-sourced data (employee count, revenue, funding, tech stack, work emails, LinkedIn, and custom fields) using the @brightdata/enrich CLI. Use this skill whenever the user wants to enrich, augment, fill in, or research rows of a spreadsheet or CSV — leads, prospects, accounts, contacts, a CRM export, or any table of companies/domains/emails — or mentions Bright Data enrichment, the `enrich` command, lead enrichment, data enrichment, or "add a column with X" to a list. Covers first-time onboarding (Bright Data + OpenRouter setup), running enrichments, and publishing this skill on skills.sh.

- Skill: `brightdata/enriching-tables` (Agent Skill, multi-file: 5 files)
- Install (CLI): `npx skillmds@latest add brightdata/enriching-tables`
- Raw SKILL.md: https://api.skillmd.com/api/skills/brightdata/enriching-tables/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Data & Analytics
- Author: brightdata (https://skillmd.com/u/brightdata)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/brightdata/enriching-tables

---


# Enriching Tables with @brightdata/enrich

`@brightdata/enrich` (CLI command: `enrich`) turns a flat CSV into an enriched one. Each row is researched on the live web through Bright Data's infrastructure and an LLM agent swarm, and new columns are appended — company size, funding, tech stack, work emails, LinkedIn URLs, or anything you can describe in plain English. Every run is resumable, streams progress, and reports cost.

This skill takes a user from zero (no account) to a finished enriched CSV, and assumes nothing about prior Bright Data experience.

## When you reach for this

Any time a user has a table and wants more columns sourced from the web: a list of company domains that needs employee counts and funding stages, a Salesforce export missing industries, a contact list that needs verified work emails, or a vague "can you find X for each of these." If they hand you a CSV and describe data they don't yet have, this is the tool.

## The shape of the work

The flow is always the same four beats. Do them in order; don't skip the dry run.

```
Enrichment Progress:
- [ ] 1. Confirm prerequisites (Node ≥20, four credentials resolve)
- [ ] 2. Inspect the input CSV (identifier column, what's already filled)
- [ ] 3. Dry-run to lock config + estimate cost, then get the user's OK
- [ ] 4. Run the real enrichment, report output path + cost
```

Copy that checklist into your working notes and tick items off — it keeps you from spending the user's money before they've approved the plan.

## Step 1 — Prerequisites

The CLI needs **Node.js ≥ 20** and **four credentials**. If the user has never set this up, walk them through `references/onboarding.md` — it covers creating a Bright Data account, provisioning the two required zones, and getting an LLM key, with where-to-click pointers. Don't paraphrase those steps from memory; read that file and follow it.

The four credentials:

| Variable | What it is | Where it comes from |
|---|---|---|
| `BRIGHT_DATA_API_KEY` | Bright Data account API token | Bright Data dashboard → Settings → API keys |
| `BRIGHT_DATA_SERP_ZONE` | name of a **SERP API** zone | Bright Data dashboard → Proxies & Scraping → your SERP zone |
| `BRIGHT_DATA_UNLOCKER_ZONE` | name of a **Web Unlocker** zone | Bright Data dashboard → Proxies & Scraping → your Unlocker zone |
| `OPENROUTER_API_KEY` | LLM provider key | openrouter.ai/keys (or use `OPENAI_API_KEY` / `ANTHROPIC_API_KEY` instead) |

There are two ways to supply them. **Environment variables** (or a `.env` file in the working directory) always take precedence, which is what you want for scripted/non-interactive runs:

```bash
export BRIGHT_DATA_API_KEY=...
export BRIGHT_DATA_SERP_ZONE=...
export BRIGHT_DATA_UNLOCKER_ZONE=...
export OPENROUTER_API_KEY=...
```

Or the user can store them once with the interactive setup (saved to a `0600` config file in their OS config dir):

```bash
npx @brightdata/enrich login
```

`login` validates each credential against the live API before saving — a wrong key fails fast here rather than mid-run. To wipe stored credentials, `enrich logout`.

**Verify before doing anything else.** Run the bundled preflight, which checks the Node version and confirms all four credentials resolve (via a dry run, so it spends nothing):

```bash
bash scripts/preflight.sh path/to/input.csv
```

If it reports a missing credential, send the user to `references/onboarding.md` for the one that's missing rather than guessing.

## Step 2 — Inspect the CSV

Look at the file before configuring the run. You need to know two things:

- **The identifier column** — the column the agents use to find each entity on the web. A company **domain** or **website** is ideal; a company **name** works; for people, an **email** plus first/last name columns. The CLI auto-detects this, but eyeball it so you can override with `--column` if the guess would be wrong (e.g. a file with both `domain` and `personal_domain`).
- **What's already filled** — there's no point (and no spend) re-fetching columns the file already has. Enrich the gaps.

A quick `head` of the file is enough. For the example file in this repo:

```bash
head -5 examples/companies.csv
# company,domain,hq_country
# Stripe,stripe.com,United States
# ...
```

Here `domain` is the natural identifier.

## Step 3 — Dry run, then get approval

**Never kick off a paid run without a dry run first.** `--dry-run` resolves the full config — identifier column, the exact fields it will add, output path, and a cost estimate — and exits without touching any API.

```bash
npx @brightdata/enrich examples/companies.csv \
  --describe "employee count, total funding raised, primary tech stack" \
  --dry-run
```

You'll get back something like the columns it will add, the detected identifier, and `Estimated: ~$X.XX (Bright Data) + ~$Y.YY (LLM)`. **Show the user this estimate and the field list, and wait for an explicit go-ahead** before the real run — especially for files over a few dozen rows. Cost scales with rows × fields; a 5,000-row file is real money.

Decide **how to specify fields** (see the full catalog in `references/fields.md`):

- `--describe "<plain english>"` — natural language. The CLI first tries to map your words onto preset fields; if it can't, an LLM designs custom fields from the description. Use this for anything bespoke ("their Series B lead investor", "whether they use Kubernetes").
- `--fields a,b,c` — exact preset field names, comma-separated. Faster and deterministic. Use when you know the names. `--describe` and `--fields` are mutually exclusive.

## Step 4 — Run it

Once approved, drop `--dry-run`:

```bash
npx @brightdata/enrich examples/companies.csv \
  --describe "employee count, total funding raised, primary tech stack"
```

The enriched file is written to `<input>.enriched.csv` by default (override with `-o`). Progress streams to stderr with a live cost meter and ETA; the final summary prints rows done/skipped/errored, total cost split by LLM vs Bright Data, and the output path. **Report that summary and the output path back to the user.**

### The options that matter most

| Option | Use it when | Default |
|---|---|---|
| `--describe "<text>"` | You want fields in plain English (incl. custom) | — |
| `--fields a,b,c` | You know the exact preset names | — |
| `--column <name>` | Auto-detection picks the wrong identifier | auto |
| `--first-name <col>` / `--last-name <col>` | Enriching **people** — lets agents disambiguate same-company contacts | — |
| `-o, --output <path>` | You want a specific output filename | `<input>.enriched.csv` |
| `--concurrency <n>` | Tune rows-in-flight (lower if rate-limited, higher to go faster) | 30 |
| `--dry-run` | Always, before a real run | off |
| `--json` | You need machine-readable NDJSON instead of a CSV (pipe to `jq`) | off |
| `--no-resume` | You want to overwrite rather than continue a prior run | resume on |
| `-q` / `-v` | Quiet (summary only) / verbose (every agent step) | normal |

### Resuming is automatic

If a run is interrupted (Ctrl-C, crash, or you just stop it), **re-run the exact same command** and it picks up where it left off — it checks the existing output's header and skips rows already written. This only works if the field set matches, so keep `--describe`/`--fields` identical. To start fresh instead, pass `--no-resume` or delete the output file. This makes large files safe to run in chunks.

### Enriching people, not just companies

For contact-level data (work email, LinkedIn, title, seniority), point the CLI at the name columns so it can tell two people at the same company apart:

```bash
npx @brightdata/enrich contacts.csv \
  --first-name first_name --last-name last_name --column work_email \
  --fields person_email,person_linkedin_url,person_title,person_seniority
```

## Cost — set expectations honestly

Bright Data bills roughly **$0.0015 per tool call**; a typical row touches 5–15 calls depending on how much you ask for. LLM cost is separate and paid to your provider. As a rule of thumb a 5-field CRM fill is well under a cent of Bright Data spend per row; deep person+company enrichment runs a few cents. The `--dry-run` estimate is your source of truth — always surface it. Compared to commercial enrichment vendors at $0.50–$2.00/row, this is one to two orders of magnitude cheaper, but it is **not free**, so confirm before large runs.

## When something goes wrong

For credential errors, header-mismatch on resume, empty-field results, rate limits, and other failure modes, see `references/troubleshooting.md` — match the error message to its row and follow the fix. Don't retry a failing command unchanged; diagnose first.

## Field catalog

The 36 built-in preset fields and 6 quick-start bundles (Startup Prospecting, Enterprise Research, Quick CRM Fill, Competitor Analysis, Person Lookup, Full Company + Person) are listed with descriptions in `references/fields.md`. Read it when the user wants specific named fields or you need to translate a request into the right `--fields` list.

## Installing / publishing this skill

This skill lives at `skills/enriching-tables/SKILL.md` in the `brightdata/open-enrich` repo — the layout skills.sh indexes automatically — so users install it with `npx skills add brightdata/open-enrich/skills/enriching-tables`. Listing details and the README badge are documented in the repo's main README ("Or drive it from your coding agent"); publishing is a one-time author task, not part of running an enrichment.

