JobsPipe
API Reference

Stack Scan

Detect a website's technology stack with POST /v1/stack/scan.

POST https://api.jobspipe.dev/v1/stack/scan

Given a domain, returns the technologies it serves - frontend frameworks, analytics, CDNs, payment processors, and SaaS widgets - detected from its live homepage. Results are cached, and a domain's history keeps a new entry only when its stack changes. Requires authentication.

Prefer to explore interactively? The API Explorer has a live playground with the request body, the full response schema, and a "try it" panel.

Request

The body is a JSON object with a single required domain.

FieldTypeDescription
domainstringRequired. The domain to scan, e.g. stripe.com. URLs and a leading www. are normalized off.
modestringOptional. auto (default) tries a fast HTTP fetch, then a headless render if the results are thin.
curl https://api.jobspipe.dev/v1/stack/scan \
  -H "Authorization: Bearer jp_live_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{ "domain": "stripe.com" }'
import requests

resp = requests.post(
    "https://api.jobspipe.dev/v1/stack/scan",
    headers={"Authorization": "Bearer jp_live_your_key_here"},
    json={"domain": "stripe.com"},
)
resp.raise_for_status()
result = resp.json()
for tech in result["detected"]:
    print(tech["name"], "-", ", ".join(tech["categories"]))
const resp = await fetch("https://api.jobspipe.dev/v1/stack/scan", {
  method: "POST",
  headers: {
    Authorization: "Bearer jp_live_your_key_here",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ domain: "stripe.com" }),
});
const result = await resp.json();
for (const tech of result.detected) {
  console.log(tech.name, "-", tech.categories.join(", "));
}

Response

A 200 response describes the domain's current stack:

  • detected - an array of detected technologies. Each has name, slug, categories, a confidence score (0-100), an optional version, and metadata such as website, saas, and oss.
  • scanned_at - when this stack snapshot was recorded. A new snapshot is stored only when the detected stack changes, so this is effectively "the stack has been this way since".
  • http_status - how the domain responded when scanned.
200 OK
{
  "domain": "stripe.com",
  "scanned_at": "2026-06-25T05:56:00Z",
  "http_status": 200,
  "detected": [
    {
      "slug": "react",
      "name": "React",
      "categories": ["JavaScript frameworks"],
      "confidence": 100,
      "version": null,
      "website": "https://react.dev",
      "saas": false,
      "oss": true
    },
    {
      "slug": "cloudflare",
      "name": "Cloudflare",
      "categories": ["CDN"],
      "confidence": 100,
      "version": null,
      "website": "https://www.cloudflare.com",
      "saas": true,
      "oss": false
    }
  ]
}

A reachable domain with no recognizable technologies returns http_status: 200 and an empty detected array. A domain the scanner could not reach returns http_status: 0.

Each call costs 1 credit against your plan's monthly quota, and counts against the per-second rate limit. A repeat scan of the same domain within the freshness window is served from cache and still costs 1 credit. See plans.

Status codes

StatusMeaning
200Success
400Missing or invalid domain
401Missing or invalid API key
402Monthly request quota exceeded
429Per-second rate limit exceeded
502The scanner failed
504The scan timed out

See the error reference for handling guidance.

On this page