How to Enrich a List of Companies
You have a CSV of company domains from signups and sales lists, and you want to enrich each record with company name, size, revenue, location, IAB categories, logo, tech stack, and related domains—so your CRM, ad targeting, or analytics pipelines can act on it. By the end of this guide you’ll be able to enrich one domain at a time via a simple REST call, loop through your CSV, cache results per domain, and handle unknown or new domains gracefully using Klazify.
Why Klazify is the right API for enriching company lists
When your goal is to enrich a list of companies from their domains, accuracy, coverage, and consistent response structure matter as much as speed. Klazify’s domain intelligence endpoint gives you the fields engineers typically need to complete a firmographic and categorical profile from a single URL or domain.
- Accurate website categorization using AI: Enrichment is only useful if the industry tag is correct. Klazify analyzes full website content (not just WHOIS or meta tags) to assign granular categories and business tags you can safely write into downstream models.
- Global coverage: Lists rarely stick to a single country. Klazify handles websites in multiple languages so your enrichment jobs don’t stall on non-English domains.
- Real-time classification: Many lists include fast-changing companies. Klazify analyzes the live site so you can keep IAB categories and tags relevant for current campaigns and routing rules.
- Industry-level categories with IAB mapping: If you need ad-tech compatible enrichment, Klazify maps to the IAB taxonomy so you can connect company domains to targeting, brand safety, and content filtering policies.
- Simple API integration: One REST endpoint returns classification plus company data, logo, social detection, tech stack indicators, registration signals, and similar domains—ideal for one-call-per-domain batch jobs.
- Compliance and filtering ready: With brand-safety aligned categories and content analysis, you can route or block domains during onboarding or auditing.
If you want to try it now, create a free account and get an API key: Register. You can review the endpoint and response fields here: Documentation.
What you get back from the categorize endpoint
Klazify’s main enrichment call is a single endpoint that accepts a domain or URL and returns categories, company info, logo URL, social detection, technology tags, domain registration data, and similar domains. Here’s the official example response format—use it to design your schema, mappers, and unit tests.
{
"domain": {
"categories": [
{
"confidence": 0.92,
"name": "/Computers & Electronics/Consumer Electronics",
"IAB-632-596": "Consumer Electronics/Technology & Computing/Consumer Electronics"
},
{
"confidence": 0.89,
"name": "/Internet & Telecom/Mobile & Wireless/Mobile Phones"
}
],
"social_media": null,
"logo_url": "https://klazify.s3.amazonaws.com/2110787991611585019600ed5fb1d1300.04730104.png"
},
"success": true,
"objects": {
"company": {
"url": "https://www.apple.com/",
"name": "Apple",
"city": "Cupertino",
"stateCode": "CA",
"countryCode": "US",
"employeesRange": "100K+",
"revenue": 274515000000,
"raised": null,
"tags": [
"E-commerce",
"Consumer Electronics",
"Mobile",
"B2C"
],
"tech": [
"omniture_adobe_analytics",
"atlassian_confluence",
"successfactors",
"apache_apex",
"talend",
"oracle_peoplesoft",
"salesforce",
"stripe",
"dell_boomi_atomsphere",
"gigya",
"sage_50cloud",
"quickbooks",
"webmethods",
"apache_tomcat",
"alteryx",
"tibco_rendezvous",
"atlassian_jira",
"..."
]
}
},
"domain_registration_data": {
"domain_age_date": "1987-02-19",
"domain_age_days_ago": "13026",
"domain_expiration_date": "2030-02-20",
"domain_expiration_days_left": "123"
},
"similar_domains": [
"bestbuy.com",
"icloud.com",
"microsoft.com",
"macrumors.com",
"google.com",
"samsung.com",
"twitter.com",
"hp.com",
"bhphotovideo.com",
"dell.com"
]
}
Key fields you’ll typically write to your enrichment table:
- domain.categories: Use name for broad category logic and IAB-632-596 when mapping to an IAB-based taxonomy. confidence helps during conflict resolution across sources.
- domain.logo_url: Store once per domain and serve cached logos in product UI.
- objects.company: Use name, url, city/stateCode/countryCode, employeesRange, revenue, and tags for firmographics. tech is useful for product qualification and TAM analysis.
- domain_registration_data: Age and expiration fields are useful for fraud checks, lifecycle scoring, and renewal monitoring.
- similar_domains: Seed “related accounts” widgets, competitive analysis, or domain clustering jobs.
Test a single domain with curl
Before you batch over a CSV, validate the call and your JSON parsing with a single domain. The example below uses a well-known publisher domain to demonstrate the request/response flow. Replace YOUR_API_KEY with your key from the dashboard.
curl -s -X GET "https://www.klazify.com/api/categorize?url=https://cbsnews.com" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Accept: application/json"
Notes for a clean test:
- Use the fully qualified URL including scheme (https://) to ensure page-level analysis where relevant.
- Persist the full raw JSON on first run so you can inspect fields and adjust your mappers without re-calling the API.
- Failed or unreachable calls are not billed, but still handle them with retries and backoff so your job completes.
Enriching a CSV list: pipeline design
Klazify processes one domain per request. For list enrichment, stream your CSV and make one API call per row with domain or URL normalization (lowercasing, trimming http/https and trailing slashes where appropriate). Implement a small in-memory or Redis/LRU cache keyed by the normalized domain to avoid duplicate calls within a single run.
Suggested processing steps
- Normalize input: Extract domain from email (after @) or from a pasted URL. Lowercase, remove tracking query strings for consistency.
- Deduplicate: Hash-set domains before calling the API to minimize calls.
- Call Klazify: One request per unique domain. Respect rate limits by spacing requests or using a small concurrency pool.
- Map fields: Convert domain.categories, objects.company, logo_url, registration data, and similar_domains into your enrichment schema.
- Cache results: Store the full JSON per domain with an update timestamp so you can rehydrate without re-calling for adjacent systems.
- Retry and fallbacks: Use exponential backoff for transient errors. On persistent failures, write a null-enriched record with an error code for re-run.
Code: call, parse, and map to an enrichment record (Python)
The snippet below demonstrates a simple call to the endpoint, reading the fields you’ll likely store, and returning a normalized enrichment object you can upsert into your CRM or warehouse.
import os
import time
import json
import requests
from urllib.parse import urlparse
API_KEY = os.getenv("KLAZIFY_API_KEY", "YOUR_API_KEY")
BASE_URL = "https://www.klazify.com/api/categorize"
def normalize_domain(value: str) -> str:
if not value:
return ""
v = value.strip().lower()
if "://" in v:
parsed = urlparse(v)
host = parsed.netloc
return host.lstrip("www.")
# likely a bare domain or email
if "@" in v:
host = v.split("@", 1)[1]
return host.lstrip("www.")
return v.lstrip("www.")
def fetch_domain_data(domain_or_url: str) -> dict:
url_param = domain_or_url if domain_or_url.startswith("http") else f"https://{domain_or_url}"
headers = {
"Authorization": f"Bearer {API_KEY}",
"Accept": "application/json",
"User-Agent": "klazify-enrichment/1.0"
}
resp = requests.get(BASE_URL, params={"url": url_param}, headers=headers, timeout=20)
if resp.status_code == 429:
# basic backoff example
time.sleep(2.0)
resp = requests.get(BASE_URL, params={"url": url_param}, headers=headers, timeout=20)
resp.raise_for_status()
return resp.json()
def map_enrichment(payload: dict) -> dict:
domain = payload.get("domain", {}) or {}
company = (payload.get("objects", {}) or {}).get("company", {}) or {}
reg = payload.get("domain_registration_data", {}) or {}
out = {
"success": payload.get("success"),
"company_name": company.get("name"),
"company_url": company.get("url"),
"location_city": company.get("city"),
"location_state": company.get("stateCode"),
"location_country": company.get("countryCode"),
"employees_range": company.get("employeesRange"),
"revenue": company.get("revenue"),
"tags": company.get("tags", []),
"tech": company.get("tech", []),
"logo_url": domain.get("logo_url"),
"categories": domain.get("categories", []),
"domain_age_date": reg.get("domain_age_date"),
"domain_age_days_ago": reg.get("domain_age_days_ago"),
"domain_expiration_date": reg.get("domain_expiration_date"),
"domain_expiration_days_left": reg.get("domain_expiration_days_left"),
"similar_domains": payload.get("similar_domains", [])
}
return out
def enrich_one(value: str) -> dict:
dom = normalize_domain(value)
data = fetch_domain_data(dom)
return map_enrichment(data)
if __name__ == "__main__":
# Example usage; replace with your CSV loop
test_value = "https://cbsnews.com"
record = enrich_one(test_value)
print(json.dumps(record, indent=2))
How to use the returned fields:
- Write categories[0].name and categories[0].confidence into “primary_category” and “primary_confidence” columns; keep the full array as JSONB for multi-category logic.
- Use objects.company.employeesRange and revenue for routing leads to SMB vs Enterprise queues.
- Store logo_url and serve it via your CDN or proxy with a daily refresh if you want consistency.
- tags and tech work well for qualification scores (e.g., prioritize companies running a tool your product integrates with).
- domain_registration_data fields enable signals like “new domain” or “soon-to-expire” for risk filters.
Field mapping guide
Most enrichment pipelines need a simple, consistent mapping from the Klazify response to your internal schema or taxonomy. Use this table to align fields you’re likely to consume.
| Klazify field | Type | Suggested target | Notes |
|---|---|---|---|
| domain.categories[].name | string | primary_category, secondary_category | Keep order; first element is typically the strongest signal. |
| domain.categories[].confidence | float | category_confidence | Use thresholds to resolve conflicts with other sources. |
| domain.categories[].IAB-632-596 | string | iab_category | Map to IAB-based targeting and filtering systems. |
| domain.logo_url | string (URL) | logo_url | Cache and proxy as needed for UI stability. |
| objects.company.name | string | company_name | Use as display name if CRM is empty. |
| objects.company.employeesRange | string | employee_band | Define routing tiers around ranges. |
| objects.company.revenue | number | revenue | Store as numeric; use currency logic in your app. |
| objects.company.city/stateCode/countryCode | strings | hq_city/state/country | Normalize region codes for analytics. |
| objects.company.tags | array | business_tags | Great for qualification and segmentation. |
| objects.company.tech | array | tech_stack | Join to partner and integration scoring. |
| domain_registration_data.* | mixed | domain_age, expiry | Use for fraud checks, risk scoring. |
| similar_domains | array | related_domains | Power “similar accounts” widgets. |
Operational details that make enrichment reliable
- Batching and concurrency: The endpoint processes one domain per call. Use a small worker pool (e.g., 5–20 concurrent requests depending on your environment) and add jittered backoff on 429/5xx. Keep a queue so you can resume after transient failures.
- Caching strategy: Cache the entire JSON per domain with a TTL that matches your update policy (e.g., weekly or monthly). In-run caching prevents duplicate calls when the same domain appears multiple times across CSVs.
- Unknown or new domains: If a domain has little to no content or is unreachable, you may get limited fields. Write a null-enriched record with a retry_at timestamp and reattempt after a delay. Failed or unreachable calls are not billed.
- Normalization: Normalize to a canonical domain (example.com) but prefer calling with a full URL (https://example.com) to enable page-level analysis where that matters. Store both original input and canonical.
- Idempotency and auditing: Persist request URL and a response hash. On re-runs, skip unchanged domains unless a force-refresh flag is set.
- Schema evolution: Keep a JSONB/variant column with the full response so you can adopt new fields (e.g., more tags or tech) without migrations.
Using categories and tags in your own taxonomy
Many teams need to map Klazify’s category signals to an internal taxonomy. Start with a priority order and deterministic rules so your enrichment is explainable:
- Take domain.categories[0].IAB-632-596 if present and map it to a canonical industry in your taxonomy.
- If IAB is missing, use domain.categories[0].name and your mapping table.
- Use tags as secondary signals to refine or disambiguate edge cases.
- If confidence for the top category is below your threshold, fall back to objects.company.tags or route for manual review.
Tip: Keep your mapping table versioned in your repo. When you change mappings, log the previous and new value per domain so analytics remain reproducible.
Plugging the enriched data into your pipeline
Once you have the mappers in place, it’s straightforward to ship enriched data into CRMs, warehouses, or ad platforms.
- CRM enrichment: Upsert by domain or website URL. If your CRM stores accounts by email domain, apply the same normalization used before calling the API to avoid duplicates.
- Warehouse model: Create a company_enrichment table keyed by domain with columns for primary_category, iab_category, employees_range, revenue, location fields, tags, tech, domain_age_date, and logo_url, plus a raw_json column.
- Ad tech or brand safety: Use IAB categories and confidence to build allow/deny rules and contextual targeting at the domain level.
- Analytics: Roll up category distributions, revenue bands, and region counts for list quality scoring and segment health reporting.
Cost, keys, and environment setup
You can start with the Starter plan at $39.99/mo and a 7-day trial to validate your enrichment workflow end-to-end. Generate your API key in the dashboard and store it as an environment variable (e.g., KLAZIFY_API_KEY) for local and CI/CD jobs.
Get your key here: Register. For full endpoint details and field descriptions, see the Documentation. If you’re building for a multi-tenant platform, explore MCP to streamline integrations.
Quality controls and observability
Add lightweight checks so you can trust and evolve enrichment without regressions:
- Completeness thresholds: Alert if the share of domains with non-null categories or company_name drops run-over-run.
- Confidence monitoring: Track the distribution of category confidence and flag outliers for manual review.
- Retry budget: Cap retries per domain and log error codes to a dead-letter queue for triage.
- Versioning: Version your field mappings and keep a changelog. Store response timestamps to support audits.
FAQ
Can I enrich multiple domains in one request?
No. Send one request per domain or URL. For lists, loop through your CSV with a small concurrency pool.
How should I handle rate limits?
Use a worker pool with exponential backoff and jitter. If you receive a 429, delay and retry. Tune concurrency to your workload and monitor for sustained throttling.
What happens if a domain is down or unreachable?
You may receive limited or no data. Failed or unreachable calls are not billed. Implement retries with backoff and write a null-enriched record with an error flag for reprocessing.
How often should I refresh enrichment?
That depends on your use case. Many teams cache results and refresh on a weekly or monthly cadence, while refreshing immediately for high-priority accounts or when a user views a profile.
Can I rely on IAB categories for ad targeting and brand safety?
Yes. Use the IAB-632-596 field when present, along with confidence scores and your own allow/deny lists, to control placements or segment inventory.
Ready to enrich your first list? Create your free account, grab an API key, and ship your CSV job today: Register. Explore field-by-field details in the Documentation and evaluate multi-tenant scenarios with MCP.
Ready to use Klazify?
Start classifying websites, enriching company data, and exploring web intelligence.
Get Started Free