Enrich HubSpot companies with technographic data from BuiltWith using an agent skill
low complexityCost: Usage-based
Prerequisites
Prerequisites
- Claude Code, Cursor, or another AI coding agent that supports skills
- HubSpot private app token stored as
HUBSPOT_TOKEN(scopes:crm.objects.companies.read,crm.objects.companies.write) - BuiltWith API key stored as
BUILTWITH_API_KEY(Pro plan or above) - Custom HubSpot company properties:
tech_stack_crm,tech_stack_marketing,tech_stack_analytics,tech_stack_all,tech_enrichment_date
Overview
Create an agent skill that looks up what technologies your prospects use and writes the data to HubSpot. Run /tech-enrich to enrich companies that are missing tech stack data, or schedule it weekly for hands-off operation.
Step 1: Create the skill directory
mkdir -p .claude/skills/tech-enrich/scriptsStep 2: Write the SKILL.md file
Create .claude/skills/tech-enrich/SKILL.md:
---
name: tech-enrich
description: Looks up what technologies HubSpot companies use via BuiltWith. Categorizes technologies into CRM, marketing, and analytics stacks and writes them to custom HubSpot company properties.
disable-model-invocation: true
allowed-tools: Bash(python *)
---
Enrich HubSpot companies with technographic data:
1. Run: `python $SKILL_DIR/scripts/tech_enrich.py`
2. Review the per-company tech stack results
3. Confirm tech data was written to HubSpotStep 3: Write the enrichment script
Create .claude/skills/tech-enrich/scripts/tech_enrich.py:
#!/usr/bin/env python3
"""
Technographic Enrichment: HubSpot → BuiltWith → HubSpot
Looks up tech stacks for companies and writes categorized results to HubSpot.
"""
import os
import sys
import time
from datetime import datetime
try:
import requests
except ImportError:
os.system("pip install requests -q")
import requests
HUBSPOT_TOKEN = os.environ.get("HUBSPOT_TOKEN")
BUILTWITH_API_KEY = os.environ.get("BUILTWITH_API_KEY")
if not all([HUBSPOT_TOKEN, BUILTWITH_API_KEY]):
print("ERROR: Set HUBSPOT_TOKEN and BUILTWITH_API_KEY environment variables")
sys.exit(1)
HS_HEADERS = {"Authorization": f"Bearer {HUBSPOT_TOKEN}", "Content-Type": "application/json"}
CATEGORY_MAP = {
"crm": ["crm"],
"marketing": ["marketing-automation", "email", "marketing"],
"analytics": ["analytics", "web-analytics"],
}
# --- Fetch companies ---
print("Searching for companies without tech stack data...")
companies = []
after = 0
while True:
resp = requests.post(
"https://api.hubapi.com/crm/v3/objects/companies/search",
headers=HS_HEADERS,
json={
"filterGroups": [{"filters": [{
"propertyName": "tech_stack_crm",
"operator": "NOT_HAS_PROPERTY"
}]}],
"properties": ["domain", "name"],
"limit": 100,
"after": after
}
)
resp.raise_for_status()
data = resp.json()
companies.extend(data["results"])
if data.get("paging", {}).get("next"):
after = data["paging"]["next"]["after"]
else:
break
print(f"Found {len(companies)} companies to enrich\n")
# --- Process each company ---
enriched = 0
skipped = 0
for company in companies:
domain = company["properties"].get("domain")
name = company["properties"].get("name", "Unknown")
if not domain:
print(f" {name} — no domain, skipping")
skipped += 1
continue
# Call BuiltWith
bw_resp = requests.get(
"https://api.builtwith.com/v21/api.json",
params={"KEY": BUILTWITH_API_KEY, "LOOKUP": domain}
)
bw_resp.raise_for_status()
bw_data = bw_resp.json()
# Parse technologies
results = bw_data.get("Results", [])
techs = []
if results:
paths = results[0].get("Result", {}).get("Paths", [])
if paths:
techs = paths[0].get("Technologies", [])
if not techs:
print(f" {name} ({domain}) — no technologies found")
skipped += 1
time.sleep(2)
continue
# Categorize
categorized = {cat: [] for cat in CATEGORY_MAP}
for tech in techs:
tag = (tech.get("Tag") or "").lower()
cats = [c.lower() for c in (tech.get("Categories") or [])]
for category, keywords in CATEGORY_MAP.items():
if any(kw in tag for kw in keywords) or any(kw in c for kw in keywords for c in cats):
categorized[category].append(tech["Name"])
break
# Update HubSpot
properties = {
"tech_stack_crm": ", ".join(categorized["crm"]) or "None detected",
"tech_stack_marketing": ", ".join(categorized["marketing"]) or "None detected",
"tech_stack_analytics": ", ".join(categorized["analytics"]) or "None detected",
"tech_stack_all": ", ".join(t["Name"] for t in techs),
"tech_enrichment_date": datetime.now().strftime("%Y-%m-%d"),
}
requests.patch(
f"https://api.hubapi.com/crm/v3/objects/companies/{company['id']}",
headers=HS_HEADERS,
json={"properties": properties}
).raise_for_status()
enriched += 1
print(f" {name} ({domain}) — {len(techs)} technologies")
print(f" CRM: {properties['tech_stack_crm']}")
print(f" Marketing: {properties['tech_stack_marketing']}")
print(f" Analytics: {properties['tech_stack_analytics']}")
time.sleep(2) # BuiltWith rate limit
print(f"\nDone. Enriched: {enriched}, Skipped: {skipped}")Step 4: Run the skill
# Via Claude Code
/tech-enrich
# Or directly
python .claude/skills/tech-enrich/scripts/tech_enrich.pyStep 5: Schedule it (optional)
# .github/workflows/tech-enrichment.yml
name: Technographic Enrichment
on:
schedule:
- cron: '0 3 * * 0' # Weekly Sunday 3 AM UTC
workflow_dispatch: {}
jobs:
enrich:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.12'
- run: pip install requests
- run: python .claude/skills/tech-enrich/scripts/tech_enrich.py
env:
HUBSPOT_TOKEN: ${{ secrets.HUBSPOT_TOKEN }}
BUILTWITH_API_KEY: ${{ secrets.BUILTWITH_API_KEY }}Cost
- BuiltWith Pro: $295/mo for 500 API calls (
$0.59/lookup). Enterprise: $495/mo for 2,000 calls ($0.25/lookup). - HubSpot: Free within API rate limits.
- Compute: Free on GitHub Actions.
BuiltWith credits are precious
At $0.59 per lookup on the Pro plan, BuiltWith is significantly more expensive than people enrichment APIs. The script only enriches companies that don't already have tech data. Limit your batch size to high-priority accounts — don't enrich your entire company database unless you're on the Enterprise plan.
When to use this approach
- You want to test technographic enrichment on a few target accounts before committing to a recurring automation
- You need ad-hoc lookups — "what tech does this prospect's company use?"
- You want to run enrichment before a quarterly account review
- You want the categorization logic version-controlled and easily adjustable
When to move to a dedicated tool
- You need technographic data automatically enriched on every new company
- You want to track tech stack changes over time with visual dashboards
- Multiple team members need to trigger and customize the enrichment
Need help implementing this?
We build and optimize automation systems for mid-market businesses. Let's discuss the right approach for your team.