API Documentation

Everything you need to detect website tech stacks programmatically.

On this page

📦
Postman CollectionDownload JSON and import into Postman to try every endpoint instantly.

Base URL

https://stackpeek.web.app

All API endpoints are under /api/v1/.

Authentication

The free tier (GET /api/v1/detect) requires no authentication and is rate limited. For higher limits and batch scanning, include your API key in the x-api-key header:

curl -H "x-api-key: stk_your_key_here" ...

API keys use the stk_ prefix. You can generate one for free via the /api/v1/keys endpoint.

Detect Tech Stack (Free Tier)

GET /api/v1/detect No auth required

Scan a single URL and return all detected technologies with confidence scores. The URL is automatically prefixed with https:// if no protocol is provided.

Query Parameters

ParameterTypeRequiredDescription
urlstringYesThe website URL to scan (e.g. stripe.com)
curl "https://stackpeek.web.app/api/v1/detect?url=stripe.com"
const res = await fetch(
  "https://stackpeek.web.app/api/v1/detect?url=stripe.com"
);
const data = await res.json();
console.log(data.technologies);
import requests

resp = requests.get(
    "https://stackpeek.web.app/api/v1/detect",
    params={"url": "stripe.com"}
)
data = resp.json()
print(data["technologies"])

Example Response

{
  "url": "https://stripe.com/",
  "technologies": [
    { "name": "React", "category": "Frontend Framework", "confidence": 95 },
    { "name": "Next.js", "category": "Frontend Framework", "confidence": 90 },
    { "name": "Cloudflare", "category": "CDN", "confidence": 100 },
    { "name": "Stripe", "category": "Payments", "confidence": 100 }
  ],
  "categories": {
    "Frontend Framework": [
      { "name": "React", "confidence": 95 },
      { "name": "Next.js", "confidence": 90 }
    ],
    "CDN": [{ "name": "Cloudflare", "confidence": 100 }],
    "Payments": [{ "name": "Stripe", "confidence": 100 }]
  },
  "meta": {
    "technologiesDetected": 4,
    "scanDuration": "342ms",
    "timestamp": "2026-03-28T12:00:00.000Z"
  }
}

Batch Detection (Paid Tier)

POST /api/v1/detect/batch API key required

Scan up to 10 URLs in a single request. Each URL is scanned concurrently. Requires an API key on a Starter or Pro plan.

Request Body

FieldTypeRequiredDescription
urlsstring[]YesArray of URLs to scan (max 10)
curl -X POST "https://stackpeek.web.app/api/v1/detect/batch" \
  -H "x-api-key: stk_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "urls": [
      "https://stripe.com",
      "https://vercel.com",
      "https://linear.app"
    ]
  }'
const res = await fetch("https://stackpeek.web.app/api/v1/detect/batch", {
  method: "POST",
  headers: {
    "x-api-key": "stk_your_key_here",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    urls: ["https://stripe.com", "https://vercel.com"]
  }),
});
const data = await res.json();
console.log(data.results);
import requests

resp = requests.post(
    "https://stackpeek.web.app/api/v1/detect/batch",
    headers={"x-api-key": "stk_your_key_here"},
    json={"urls": ["https://stripe.com", "https://vercel.com"]}
)
for result in resp.json()["results"]:
    print(result["url"], len(result["technologies"]), "techs")

Example Response

{
  "results": [
    {
      "url": "https://stripe.com/",
      "technologies": [/* ... */],
      "status": "ok"
    },
    {
      "url": "https://vercel.com/",
      "technologies": [/* ... */],
      "status": "ok"
    }
  ],
  "meta": {
    "total": 2,
    "timestamp": "2026-03-28T12:00:00.000Z"
  }
}

Get an API Key

POST /api/v1/keys No auth required

Create a free API key. You start on the free plan with 100 scans/day.

curl -X POST "https://stackpeek.web.app/api/v1/keys" \
  -H "Content-Type: application/json" \
  -d '{"email": "you@example.com"}'
const res = await fetch("https://stackpeek.web.app/api/v1/keys", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ email: "you@example.com" }),
});
const { apiKey } = await res.json();
console.log("Your key:", apiKey);
import requests

resp = requests.post(
    "https://stackpeek.web.app/api/v1/keys",
    json={"email": "you@example.com"}
)
print(resp.json()["apiKey"])

Response

{
  "apiKey": "stk_abc123def456...",
  "plan": "free",
  "limit": "100 scans/day"
}

Check Usage

GET /api/v1/usage API key required

Check your current usage stats and plan details.

curl -H "x-api-key: stk_your_key_here" \
  "https://stackpeek.web.app/api/v1/usage"

Response

{
  "plan": "starter",
  "requestsToday": 142,
  "requestsThisMonth": 3847
}

Health Check

GET /api/health No auth required

Check if the API is up and running. Useful for monitoring and uptime checks.

curl "https://stackpeek.web.app/api/health"

Response

{
  "status": "ok",
  "service": "stackpeek",
  "version": "1.0.0"
}

Response Format

Every detection response includes three sections:

technologies

A flat array of all detected technologies. Each item contains:

FieldTypeDescription
namestringTechnology name (e.g. "React", "Cloudflare")
categorystringTechnology category (e.g. "Frontend Framework", "CDN")
confidencenumberDetection confidence from 0 to 100

categories

The same technologies grouped by category. Each key is a category name, and the value is an array of { name, confidence } objects.

meta

FieldTypeDescription
technologiesDetectednumberTotal number of technologies found
scanDurationstringTime taken to scan (e.g. "342ms")
timestampstringISO 8601 timestamp of the scan

Rate Limits

PlanDaily ScansMonthly ScansBatch
Free1001,000No
Starter5005,000Yes (10 URLs)
Pro2,50025,000Yes (10 URLs)

Rate limits reset daily at midnight UTC and monthly on the 1st. The free GET endpoint also has a per-IP rate limit to prevent abuse. If you exceed your limit, the API returns a 429 response.

Timeouts: Target URLs that don't respond within 10 seconds are aborted with a 504 response. Private/internal URLs (localhost, 127.0.0.1, 10.x, 192.168.x) are blocked.

Pricing

PlanPriceScans/dayFeatures
Free$0100Single URL detection, JSON response
Starter$9/mo500Batch scanning (10 URLs), API key, usage dashboard
Pro$29/mo2,500Everything in Starter + priority support, higher limits

Upgrade anytime at stackpeek.web.app/#pricing. All paid plans include a 7-day free trial.

Error Codes

200Scan completed successfully
400Bad request — missing url parameter, invalid URL, private/internal URL, or invalid batch body
401Unauthorized — missing or invalid API key (batch endpoint)
429Rate limit exceeded — upgrade your plan or wait until reset
502Failed to fetch target URL — the target site may be down or blocking requests
504Target URL timed out — scan aborted after 10 seconds

Error responses return JSON:

{
  "error": "Missing required parameter: url",
  "example": "/api/v1/detect?url=https://example.com"
}

Full Examples

Scan a site and list all frameworks

async function getFrameworks(url) {
  const res = await fetch(
    `https://stackpeek.web.app/api/v1/detect?url=${url}`
  );
  const { categories } = await res.json();

  const frameworks = categories["Frontend Framework"] || [];
  frameworks.forEach(fw =>
    console.log(`${fw.name} (${fw.confidence}% confidence)`)
  );
}

getFrameworks("vercel.com");
import requests

def get_frameworks(url):
    resp = requests.get(
        "https://stackpeek.web.app/api/v1/detect",
        params={"url": url}
    )
    categories = resp.json()["categories"]

    for fw in categories.get("Frontend Framework", []):
        print(f"{fw['name']} ({fw['confidence']}% confidence)")

get_frameworks("vercel.com")

Batch scan competitors

const API_KEY = "stk_your_key_here";

const res = await fetch("https://stackpeek.web.app/api/v1/detect/batch", {
  method: "POST",
  headers: {
    "x-api-key": API_KEY,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    urls: [
      "https://competitor1.com",
      "https://competitor2.com",
      "https://competitor3.com",
    ],
  }),
});

const { results } = await res.json();
results.forEach(r => {
  console.log(`\n${r.url}:`);
  r.technologies.forEach(t =>
    console.log(`  ${t.category}: ${t.name}`)
  );
});
import requests

API_KEY = "stk_your_key_here"

resp = requests.post(
    "https://stackpeek.web.app/api/v1/detect/batch",
    headers={"x-api-key": API_KEY},
    json={"urls": [
        "https://competitor1.com",
        "https://competitor2.com",
        "https://competitor3.com",
    ]}
)

for r in resp.json()["results"]:
    print(f"\n{r['url']}:")
    for t in r["technologies"]:
        print(f"  {t['category']}: {t['name']}")