VendorStacks
← All posts
Engineering6 min read

What Tech Stack Does a Company Use? Building Automated Detection Into Your Application

A technical guide to programmatically answering "what tech stack does a company use" with API-based vendor detection, including implementation patterns and real code examples.

Stax
VendorStacks research desk

The Problem: Manual Tech Stack Research Doesn't Scale

When you need to know what tech stack a company uses—whether you're qualifying leads, building competitive intelligence, or enriching user profiles—manual research breaks down quickly. Checking a company's careers page, privacy policy, and terms of service to extract vendor mentions works for 5 companies. It doesn't work for 500.

The core challenge is that vendor usage evidence is scattered across multiple public sources: subprocessor lists in privacy policies, integration documentation, API references in developer docs, and vendor badges in footers. A programmatic solution needs to scan these sources, extract structured data, and return it in a format you can use immediately.

How Tech Stack Detection Works

VendorStacks uses a deterministic extraction method: it scans public web pages (privacy policies, terms of service, careers pages, documentation) and identifies vendor mentions with quoted source evidence. When you query a domain, the API returns:

  • A categorized vendor stack across 24 categories (cloud_infra, payments, ai_ml, crm_sales, etc.)
  • The specific URL where each vendor was found
  • The exact text snippet that evidences the vendor's presence
  • A confidence score based on the strength and recency of the evidence

This approach has clear boundaries: it detects vendors that companies publicly disclose, not private infrastructure choices or vendors used without public documentation.

Basic Implementation: Single Company Lookup

The simplest use case is answering "what tech stack does this company use" for a single domain. The /v1/check endpoint handles both indexed companies (sub-second response) and new domains (triggers a live scan, 15-90 seconds).

import requests
import time

API_KEY = "vr_live_..."
BASE_URL = "https://api.vendorstacks.com"

def get_tech_stack(domain):
    headers = {"Authorization": f"Bearer {API_KEY}"}
    response = requests.get(
        f"{BASE_URL}/v1/check",
        params={"url": domain},
        headers=headers
    )
    
    if response.status_code == 202:
        # Live scan triggered, poll for results
        time.sleep(20)
        return get_tech_stack(domain)  # Retry
    
    data = response.json()
    
    if not data.get("found"):
        return {"domain": domain, "vendors": [], "note": "No public evidence found"}
    
    # Extract vendors by category
    vendors_by_category = {}
    for category, vendors in data["vendor_stack"].items():
        if vendors:  # Only include categories with vendors
            vendors_by_category[category] = vendors
    
    return {
        "domain": domain,
        "vendors_by_category": vendors_by_category,
        "scanned_at": data["scanned_at"],
        "credits_used": data["credits_used"]
    }

# Example usage
stack = get_tech_stack("stripe.com")
print(f"Found {sum(len(v) for v in stack['vendors_by_category'].values())} vendors")
for category, vendors in stack["vendors_by_category"].items():
    print(f"{category}: {', '.join(vendors)}")

Key detail: "found": false means no public evidence was located, not that the company uses no vendors. Many companies don't publicly disclose their full stack.

Pattern 1: Batch Processing with Rate Awareness

When you need tech stacks for multiple companies, the /v1/company/{domain} endpoint is more efficient. It returns data for indexed companies instantly and never triggers scans, making it ideal for bulk operations.

def batch_tech_stack_lookup(domains, batch_size=10):
    """
    Look up tech stacks for multiple domains.
    Uses /v1/company/{domain} for indexed lookups only.
    """
    headers = {"Authorization": f"Bearer {API_KEY}"}
    results = []
    
    for i in range(0, len(domains), batch_size):
        batch = domains[i:i+batch_size]
        
        for domain in batch:
            response = requests.get(
                f"{BASE_URL}/v1/company/{domain}",
                headers=headers
            )
            
            if response.status_code == 200:
                data = response.json()
                if data.get("found"):
                    results.append({
                        "domain": domain,
                        "vendor_stack": data["vendor_stack"],
                        "indexed": True
                    })
                else:
                    results.append({
                        "domain": domain,
                        "indexed": False
                    })
            elif response.status_code == 404:
                results.append({
                    "domain": domain,
                    "indexed": False
                })
        
        # Check remaining balance
        balance_response = requests.get(
            f"{BASE_URL}/v1/balance",
            headers=headers
        )
        balance = balance_response.json()["credit_balance"]
        print(f"Processed {i+len(batch)} domains. Balance: {balance} credits")
        
        if balance < 100:
            print("Warning: Low credit balance")
            break
    
    return results

# Example: enrich a list of target accounts
target_accounts = ["openai.com", "anthropic.com", "stripe.com", "hubspot.com"]
enriched = batch_tech_stack_lookup(target_accounts)

This pattern is useful when enriching existing datasets where you need tech stack data for known companies but don't want to wait for live scans.

Pattern 2: Finding Companies by Vendor (Reverse Lookup)

The inverse question—"which companies use vendor X"—is equally valuable. The /v1/prospect endpoint performs reverse lookup across the indexed dataset.

Current index coverage:

  • 1,000 companies indexed
  • 324 distinct vendors detected
  • Top vendors by company count: AWS (338 companies), Google Analytics (292), Stripe (270), OpenAI (210), Anthropic (171)
def find_companies_using_vendor(vendor_name, max_results=50):
    """
    Find companies using a specific vendor.
    Pagination: 10 results per page.
    Cost: 1 credit per result returned (0 credits if no results).
    """
    headers = {"Authorization": f"Bearer {API_KEY}"}
    all_companies = []
    page = 1
    
    while len(all_companies) < max_results:
        response = requests.get(
            f"{BASE_URL}/v1/prospect",
            params={
                "vendor": vendor_name,
                "page": page
            },
            headers=headers
        )
        
        data = response.json()
        companies = data.get("companies", [])
        
        if not companies:
            break
        
        all_companies.extend(companies)
        
        if len(companies) < 10:  # Last page
            break
        
        page += 1
    
    return all_companies[:max_results]

# Example: build a prospect list of Anthropic users
anthropic_users = find_companies_using_vendor("Anthropic", max_results=30)
print(f"Found {len(anthropic_users)} companies using Anthropic")

# Cross-reference with another vendor
stripe_users = set(find_companies_using_vendor("Stripe", max_results=100))
anthropic_and_stripe = [c for c in anthropic_users if c in stripe_users]
print(f"{len(anthropic_and_stripe)} companies use both Anthropic and Stripe")

This is particularly useful for competitive intelligence ("who uses competitor X") and market segmentation ("AI companies using modern payment infrastructure").

Pattern 3: Tech Stack Enrichment in a Webhook Flow

If you're building a product that onboards new users and you want to enrich their profile with tech stack data, you can integrate the API into your signup or webhook flow.

from flask import Flask, request, jsonify
import requests

app = Flask(__name__)

@app.route("/webhook/new-signup", methods=["POST"])
def handle_new_signup():
    """
    Webhook handler for new user signups.
    Enriches user record with tech stack data.
    """
    payload = request.json
    user_email = payload["email"]
    user_domain = user_email.split("@")[1]
    
    # Get tech stack (use /v1/company for instant response)
    headers = {"Authorization": f"Bearer {API_KEY}"}
    tech_stack_response = requests.get(
        f"{BASE_URL}/v1/company/{user_domain}",
        headers=headers
    )
    
    enrichment_data = {"domain": user_domain}
    
    if tech_stack_response.status_code == 200:
        data = tech_stack_response.json()
        if data.get("found"):
            # Extract key categories for segmentation
            enrichment_data["uses_stripe"] = "Stripe" in data["vendor_stack"].get("payments", [])
            enrichment_data["uses_openai"] = "OpenAI" in data["vendor_stack"].get("ai_ml", [])
            enrichment_data["uses_anthropic"] = "Anthropic" in data["vendor_stack"].get("ai_ml", [])
            enrichment_data["cloud_provider"] = data["vendor_stack"].get("cloud_infra", [])
            enrichment_data["has_tech_stack"] = True
        else:
            enrichment_data["has_tech_stack"] = False
    
    # Update user record in your database
    # update_user(user_email, enrichment_data)
    
    return jsonify({"status": "enriched", "data": enrichment_data})

This pattern lets you segment users immediately based on their company's tech stack without manual research.

Cost Optimization: Understanding the Billing Model

VendorStacks bills 1 credit per successful lookup and 1 credit per reverse-lookup result. Critically, you're only charged for results:

  • A lookup that finds no evidence: 0 credits
  • A failed scan: 0 credits
  • A reverse lookup with no results: 0 credits

Pricing tiers:

  • $10 for 1,100 credits ($0.009/credit)
  • $50 for 6,000 credits ($0.008/credit)
  • $250 for 35,000 credits ($0.007/credit)

Optimization strategies:

  1. Use /v1/company/{domain} for batch operations: Never triggers scans, so you only pay for indexed companies with data.
  1. Cache results: Tech stacks don't change daily. Cache results for 30-90 days and only refresh when needed.
  1. Filter before lookup: If you're enriching a large list, filter by domain age, company size, or other signals before calling the API.
  1. Reverse lookup first for specific vendors: If you only care about companies using Stripe, use /v1/prospect?vendor=Stripe instead of checking every company individually.

Categories and Vendor Coverage

The API organizes vendors into 24 categories:

  • Infrastructure: cloud_infra (AWS, Google Cloud, Azure), database_infra (Snowflake, PostgreSQL), observability (Datadog, Sentry)
  • Revenue: payments (Stripe, PayPal), ecommerce_pos (Shopify, WooCommerce), finance_accounting (QuickBooks, Stripe Tax)
  • GTM: crm_sales (Salesforce, HubSpot), marketing_ads (Google Ads, Facebook), support_cx (Intercom, Zendesk)
  • Product: ai_ml (OpenAI, Anthropic), analytics_data (Google Analytics, Segment), auth_identity (Auth0, Okta)
  • Compliance: privacy_compliance (OneTrust, Osano), security_fraud (Stripe Radar, Sift)

Current index includes 324 distinct vendors across these categories. The most common:

  • AWS: 338 companies
  • Google Analytics: 292 companies
  • Stripe: 270 companies
  • OpenAI: 210 companies
  • Anthropic: 171 companies
  • Cloudflare: 162 companies

Evidence and Confidence Scoring

Every vendor detection includes evidence fields:

# Example response structure
{
  "vendor_stack": {
    "payments": ["Stripe"],
    "ai_ml": ["OpenAI"]
  },
  "stripe_evidence": {
    "url": "https://example.com/privacy",
    "text": "We use Stripe (https://stripe.com) to process payments...",
    "confidence": 0.95
  },
  "openai_evidence": {
    "url": "https://example.com/terms",  
    "text": "Our AI features are powered by OpenAI's GPT-4 API...",
    "confidence": 0.92
  }
}

Confidence scores are based on:

  • Explicit vendor mentions with URLs
  • Context (privacy policy mentions are stronger than blog posts)
  • Recency of the evidence

You can filter by confidence threshold if you need high-precision results.

Getting Started

To implement tech stack detection:

  1. Generate an API key at the /v1/keys endpoint (instant, 25 free credits)
  2. Test with /v1/check?url=stripe.com to see response structure
  3. Check your balance with /v1/balance
  4. Implement one of the patterns above based on your use case

The API returns structured data you can use immediately—no additional parsing or cleaning required.

About the author

Stax is the pangolin who fronts the VendorStacks research desk — a fitting mascot for a company that reads layered stacks for a living. Posts under this byline are written by the VendorStacks team.

VendorStacks is the subprocessor disclosure data API — structured vendor stacks with quoted evidence, 25 free credits to start.

Get an API key