# Netzhandwerker Traffic Classifier

> Netzhandwerker Traffic Classifier is a paid API for AI agents from tools.halowerk.com, paid per call via x402, $0.004/call, status unknown (last checked 2026-10-12).

Classifies web access log records into human vs. bot clients with multi-signal scoring, grouping records by IP/user-agent and explaining each classification signal.

## Facts

- Endpoint: POST https://tools.halowerk.com/v1/traffic/classify?utm_source=zero.xyz
- Price: $0.004/call
- Payment: x402
- Status: unknown
- Last checked: 2026-10-12
- Activations on Zero: 0
- Tags: x402
- Canonical page: https://www.zero.xyz/c/netzhandwerker-traffic-classifier-15b1a9ec
- Structured record (JSON): https://api.zero.xyz/v1/capabilities/cap_VoM0Y4sEsbfzqOmzGw5C0

Status and success rate cover calls made through Zero and Zero's own probes. Third-party monitors may report differently.

## How to call it through Zero

Zero handles the 402 payment challenge and records the run. With the Zero CLI installed (`npm i -g @zeroxyz/cli`):

```sh
zero fetch --capability netzhandwerker-traffic-classifier-15b1a9ec -d '<json body>'
```

Example prompt: I have 500 access log records from the past hour — can you classify them as human or bot traffic, grouping by IP and user agent, and tell me what signals tipped the classification for each client?

## When to prefer this

Choose this endpoint when you have raw web access logs and need explainable, signal-based bot/human classification without storing any PII. It is especially useful when you want per-signal reasoning (not just a binary label), need privacy-preserving IP anonymization, or want to handle batches up to 2000 records in a single call. Prefer it over generic IP reputation lookups when cadence patterns, path shape, and method mix matter for your classification logic.

## Known failure modes

- Request body exceeds 256 KB limit — reduce record count or field verbosity
- Records missing required 'path' or timestamp fields are rejected
- Unrecognized field names in records cause rejection rather than silent ignore
- Fewer than min_requests_per_client requests causes client to be skipped and counted in clients_skipped
- max_clients or session_gap_s outside allowed ranges returns validation error
- Malformed ISO 8601 timestamps or negative Unix timestamps cause parse errors

## How this service works

Groups the access records you pass into clients and sorts each in two stages: person or machine, then, for a machine, the purpose. Signals: cadence and its scatter, path shape and consecutive numeric runs, asset share, referer, method mix, not-found share, robots.txt, user agent product token. Each signal returns what was observed, its weight and why. A lead under two points stays unknown. Nothing is stored, no raw IP is returned: IPv4 cut to /24, IPv6 to /48.

## Output

Returns grouped client records with a two-stage classification (person or machine, then machine purpose), a numeric lead score, and per-signal breakdowns showing the observed value, weight, and rationale. Clients with a lead under two points remain 'unknown'. IPv4 addresses are truncated to /24, IPv6 to /48. No raw IPs or raw data are stored.

## Request schema (JSON Schema)

```json
{
 "type": "object",
 "properties": {
  "group_by": {
   "enum": [
    "ip",
    "user_agent",
    "ip_user_agent",
    "none"
   ],
   "type": "string",
   "default": "ip_user_agent",
   "description": "How records are grouped into clients."
  },
  "requests": {
   "type": "array",
   "items": {
    "type": "object",
    "anyOf": [
     {
      "required": [
       "time_unix_s"
      ]
     },
     {
      "required": [
       "time"
      ]
     }
    ],
    "examples": [
     {
      "ip": "203.0.113.44",
      "path": "/products/100",
      "method": "GET",
      "status": 200,
      "user_agent": "python-requests/2.32.3",
      "time_unix_s": 1786000000
     }
    ],
    "required": [
     "path"
    ],
    "properties": {
     "ip": {
      "type": "string",
      "description": "Client IPv4 or IPv6 address; output is masked."
     },
     "path": {
      "type": "string",
      "minLength": 1,
      "description": "Requested path, including a query string if relevant."
     },
     "time": {
      "type": "string",
      "description": "Request time as an ISO 8601 timestamp."
     },
     "bytes": {
      "type": "integer",
      "minimum": 0,
      "description": "Response body size in bytes."
     },
     "method": {
      "type": "string",
      "description": "HTTP method such as GET or POST."
     },
     "status": {
      "type": "integer",
      "maximum": 599,
      "minimum": 100,
      "description": "HTTP response status."
     },
     "referer": {
      "type": "string",
      "description": "Referer header value."
     },
     "user_agent": {
      "type": "string",
      "description": "User-Agent header value."
     },
     "time_unix_s": {
      "type": "number",
      "description": "Request time as Unix seconds."
     }
    },
    "additionalProperties": false
   },
   "maxItems": 2000,
   "minItems": 1,
   "description": "Access records. Each needs path and either time_unix_s or time. The service caps the whole request body at 256 KB, so long records reach that limit before maxItems."
  },
  "max_clients": {
   "type": "integer",
   "default": 100,
   "maximum": 500,
   "minimum": 1,
   "description": "How many clients are reported, largest first."
  },
  "session_gap_s": {
   "type": "integer",
   "default": 1800,
   "maximum": 86400,
   "minimum": 60,
   "description": "Silence after which the next request starts a new session."
  },
  "min_requests_per_client": {
   "type": "integer",
   "default": 2,
   "maximum": 1000,
   "m
… (truncated)
```

## More

- Live health (JSON, refreshed every minute): https://www.zero.xyz/c/netzhandwerker-traffic-classifier-15b1a9ec/health.json
- [Zero catalog index](https://www.zero.xyz/llms.txt)
- [Other services from tools.halowerk.com](https://www.zero.xyz/host/tools.halowerk.com/llms.txt)
