Pre-Black Friday: 20% off, for as long as you stayEARLYBFon Solo and AgencyEnds Nov 28Start free

How-to guide

How to Test Company Enrichment Tools on the Same 500 Accounts (A 10-Vendor Harness)

Posts that claim they tested ten tools rarely publish the file. Here is the harness, so you can run it on your own accounts.

Get your free API key →Free to start. No credit card. 1,000 records to spend whenever you like.

You can compare ten enrichment tools fairly with one account file, one script per vendor and one scoring sheet. This page is that harness, not a set of results.

We have not run a ten-vendor test, and we will not invent one. A claim like "we tested 10 company enrichment tools on the same 500 accounts" is only useful if you can see the file and the scoring. So the steps below give you both, and the LeadOcean leg is runnable today.

TL;DR

  • Build one file of 500 domains from your real pipeline, score every vendor on the same fields, and judge fill rate and accuracy separately.
  • The LeadOcean leg takes about 2 hours and spends up to 500 records, inside the 1,000 on the free plan.
  • Run each vendor on its free tier or a trial export where one exists. Do not buy ten annual plans to find out.

Prerequisites

  • A LeadOcean API key in $LEADOCEAN_API_KEY (the free plan works: 1,000 records for life, no card, 5 requests a second).
  • curl, jq and Python 3.
  • Your 500 accounts as a CSV with one column named domain.
  • A free or trial login for each other vendor you want in the test.

Step 1: Pick the 500 accounts

Sample from accounts you actually sell to, not from a clean list. Take 500 domains from your CRM: mix closed-won, open pipeline and cold targets.

Include the hard cases on purpose. Aim for about a third small companies under 50 staff, a third mid-size, a third large. Add some non-US domains if you sell abroad.

bash
python3 - <<'PY'
import csv, random
rows = list(csv.DictReader(open("crm_accounts.csv")))
random.seed(42)
sample = random.sample(rows, 500)
with open("accounts.csv", "w", newline="") as f:
    w = csv.writer(f)
    w.writerow(["domain"])
    for r in sample:
        w.writerow([r["domain"].strip().lower()])
PY
wc -l accounts.csv

The fixed seed matters. Anyone should be able to rebuild your sample.

Step 2: Size the universe for free

Before you spend a record, check that your target segment exists in the data. The company count is free and exact.

bash
curl -s "https://api.leadocean.io/v1/companies/count" \
  -H "x-api-key: $LEADOCEAN_API_KEY" \
  -G \
  --data-urlencode 'industry=Software Development' \
  --data-urlencode 'employeeRange=51-200' \
  --data-urlencode 'hqCountry=US' | jq '.total'

The MCP tool leadocean_count_companies takes the same filters and costs nothing. If you only want a coarse read of coverage for your segment, this is it. It does not replace the per-account test in step 3.

Step 3: Enrich all 500 on LeadOcean

Send each domain to POST /v1/companies/enrich and save the raw JSON. Keep the raw response, because you will score it later and you will want to re-check disagreements.

python
import csv, json, os, time, urllib.request

KEY = os.environ["LEADOCEAN_API_KEY"]
URL = "https://api.leadocean.io/v1/companies/enrich"

out = open("leadocean_raw.jsonl", "w")
for row in csv.DictReader(open("accounts.csv")):
    req = urllib.request.Request(
        URL,
        data=json.dumps({"domain": row["domain"]}).encode(),
        headers={"x-api-key": KEY, "content-type": "application/json"},
        method="POST",
    )
    try:
        body = json.load(urllib.request.urlopen(req))
        out.write(json.dumps({"domain": row["domain"], "status": 200, "body": body}) + "\n")
    except urllib.error.HTTPError as e:
        out.write(json.dumps({"domain": row["domain"], "status": e.code}) + "\n")
    time.sleep(0.25)  # stays under 5 requests a second on Free
out.close()

A 404 means the company is not in the data. It costs nothing, and it is a result you must count as a miss. Do not drop those rows.

Step 4: Run the same file through the other nine

Each vendor gets the identical accounts.csv. Use whichever input the vendor supports best, but record what you used: domain, company name or LinkedIn URL. A vendor that needs a name where you gave a domain has been handicapped.

For each vendor, save three things: the raw output, the date, and the plan or tier you ran it on. If a vendor throttles a free tier below 500 lookups, say so in the sheet and test the same first N accounts on every tool.

Check each vendor's own documentation for how an unmatched account is billed. The rule differs, and it changes the real cost of your test.

Step 5: Normalize into one table

Different vendors name the same field differently. Map every output to one shared set of columns before you score anything.

python
import json, csv

FIELDS = ["domain", "name", "industry", "employee_count", "hq_country",
          "founded_year", "linkedin_url", "technologies"]

def pick(d, *paths):
    for p in paths:
        cur = d
        for k in p.split("."):
            cur = cur.get(k) if isinstance(cur, dict) else None
        if cur not in (None, "", []):
            return cur
    return None

with open("leadocean_flat.csv", "w", newline="") as f:
    w = csv.DictWriter(f, fieldnames=FIELDS)
    w.writeheader()
    for line in open("leadocean_raw.jsonl"):
        r = json.loads(line)
        data = (r.get("body") or {}).get("data") or {}
        cd = data.get("company_data") or {}
        w.writerow({
            "domain": r["domain"],
            "name": pick(cd, "name"),
            "industry": pick(cd, "industry"),
            "employee_count": pick(cd, "employee_count"),
            "hq_country": pick(cd, "hq_country"),
            "founded_year": pick(cd, "founded_year"),
            "linkedin_url": pick(cd, "linkedin_url"),
            "technologies": pick(data, "company_detected_technologies"),
        })

The key names inside company_data above are placeholders. Open one raw response from step 3 and adjust the paths to what it returns.

Step 6: Score three numbers per vendor

Score three things and never blend them into one number.

  1. Match rate: accounts returned out of 500.
  2. Fill rate per field: of the matched accounts, how many have a non-empty value in each field you care about.
  3. Accuracy: hand-check 50 randomly chosen accounts per vendor against the company's own website and LinkedIn page.

Fill rate is cheap and tempting. It is also easy to game: a tool that returns a plausible guess scores high on fill and low on accuracy. Only the hand check catches that.

python
import csv
rows = list(csv.DictReader(open("leadocean_flat.csv")))
matched = [r for r in rows if r["name"]]
print("match rate:", len(matched), "/ 500")
for f in ["industry", "employee_count", "hq_country", "founded_year"]:
    n = sum(1 for r in matched if r[f])
    print(f, "fill:", n, "/", len(matched))

Put one vendor per row and one metric per column in the sheet. Add the date you ran it. Enrichment data changes monthly, so a result older than a quarter is a stale result.

Step 7: Read the results like a buyer

Rank vendors per field, not overall. A tool that wins on headcount may lose on technologies, and you may only need one of them.

Then price the winner at your real volume. Fill rate on 500 accounts means little if the plan that delivers it costs ten times your budget at 50,000. Use monthly list price first and the billed-yearly figure after it, and write down the date you read each pricing page.

Last, look at the misses. List the accounts that every vendor failed on. They show you which gap no tool will close for you.

What you get

Step 2 returned this on 2026-10-21 from the free leadocean_count_companies tool, for US companies in the Software Development industry with 51 to 200 staff:

json
{
  "total": 9261,
  "totalIsExact": true,
  "facets": {
    "hq_state": [
      { "value": "California", "count": 2398 },
      { "value": "New York", "count": 842 },
      { "value": "Texas", "count": 776 }
    ]
  },
  "credits": 0,
  "unsupportedFilters": []
}

That is a count of companies in one segment, not a mailable count and not a fill rate. The state list is cut to three rows here.

A single enrichment answers in the shape below (response shape from the API reference, placeholder values):

json
{
  "success": true,
  "data": {
    "company_data": { "name": "Acme", "domain": "acme.com" },
    "company_detected_technologies": {},
    "company_metrics": {}
  },
  "meta": {}
}

Troubleshooting

ErrorCauseFix
401Missing or wrong x-api-key headerCheck $LEADOCEAN_API_KEY is exported in the shell that runs the script
404The company is not in the dataCount it as a miss. It costs nothing. Do not retry
429Above the plan's rate limit (5 a second on Free, 200 on Agency)Honor Retry-After, or slow the loop
402The 1,000 free records are spentMove to a paid plan, or cut the sample
Empty count or unsupportedFilters filledA bad enum value or an unsupported filterResolve values with leadocean_list_enum_values first
Export refusedOver 50,000 rows a request or 500,000 a daySplit the file. Bulk CSV export is not on Free

FAQ

Why 500 accounts?

It is large enough to show differences in fill rate and small enough to hand-check a slice. Below about 200, one odd segment can swing the result.

Can I run this entirely on the free plan?

For the LeadOcean leg, yes. 500 enrichments fit inside the 1,000 records, and misses cost nothing. Other vendors have their own free limits, so check them.

Should I test people data too?

Test it separately. Person enrich takes one of linkedin_url, email, phone or person_id, and email accuracy needs its own bounce-based check. Mixing it into the company test hides both results.

How often should I rerun it?

Once a quarter. LeadOcean refreshes its dataset monthly, and every record carries its own fetched_at date, so you can see how old a value is.

What should I do about vendors that block automated testing?

Do not work around the block. Use the vendor's own export or upload feature, or leave that vendor out and say why in your sheet. A gap you disclose is better than a number you cannot defend.

Is a vendor's own match-rate claim worth citing?

Only next to your own number. A vendor measures on its own sample. Your file has your mix of sizes, countries and industries, and that mix decides the result.

Where do I compare prices?

See the pricing page for LeadOcean. For the other nine, read each vendor's own pricing page and note the month you read it.

For background on what the fields mean, read what company enrichment is. For tool picks by use case, see the best lead enrichment tools for SaaS companies. The API itself is covered in the company enrichment API guide.

Run your own 500-account test with 1,000 free records

Free to start. No credit card. 1,000 records to spend whenever you like.

Get your free API key →