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/scripts

Step 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 HubSpot

Step 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.py

Step 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.