Skip to content

How It Works

KEPCA uses a progressive profiling approach: gather passive signals first, then escalate to active challenges only when the risk score warrants it.

Request lifecycle

Every verification follows these eight steps:

Browser                        KEPCA API                     Your Server
  |                               |                              |
  |  1. Page load — collect       |                              |
  |     passive signals           |                              |
  |                               |                              |
  |  2. POST /v1/{sk}/init ------>|                              |
  |     { signals }               |                              |
  |                               |  3. Risk scoring             |
  |  4. { session_id,             |                              |
  |       requires_challenge }    |                              |
  |  <----------------------------|                              |
  |                               |                              |
  |  5. POST /v1/{sk}/challenge ->|  (only if required)          |
  |  <-- { challenge }            |                              |
  |                               |                              |
  |  6. Solve PoW in Web Worker   |                              |
  |                               |                              |
  |  7. POST /v1/{sk}/solve ----->|                              |
  |  <-- { token }                |                              |
  |                               |                              |
  |  8. Form submit with token ---|----------------------------->|
  |                               |                              |
  |                               |  POST /v1/siteverify <-------|
  |                               |  { secret, token, ip }       |
  |                               |------> { success, score }    |

Steps 5-7 are skipped for low-risk users (tier 1). They receive a token directly after step 4.

Risk scoring

The risk engine evaluates multiple signals and assigns a composite score from 0.0 (certainly human) to 1.0 (certainly bot):

SignalWeightWhat it detects
time_on_page_msHighBots submit forms in < 1 second
submit_time_msHighTime between page load and form submit
honeypot_filledMaxOnly bots fill hidden fields
user_agentMediumKnown bot UA strings, headless browsers
tls_fingerprintMediumTLS JA3/JA4 fingerprint anomalies
request_countMediumRapid repeated requests from same source
ip_hashLowIP reputation (optional, privacy-safe)

Risk tiers

TierScore rangeAction
10.0 - 0.3Invisible pass — no challenge
20.3 - 0.6Proof-of-Work challenge
30.6 - 1.0Interactive challenge (grid, slider)

The thresholds are configurable per site via the dashboard.

Challenge types

KEPCA supports six challenge types, activated per site:

Proof of Work (PoW)

A SHA-256 hash puzzle solved in a Web Worker. The difficulty scales with the risk score. Invisible to the user — they only see a brief spinner.

Checkbox

Classic "I'm not a robot" click. Triggers the full flow behind the scenes.

Slider

Drag a slider to a target position. Adds an interaction signal.

Grid

Select matching images from a grid. Used for high-risk traffic.

Interactive

Custom interactive puzzles (map-based, pattern-based). The most resistant to automated solving.

Text

Simple text-based challenges (math problems, word completion). Accessibility-friendly fallback.

Token structure

Tokens are self-contained and HMAC-signed (HS256). They can be verified without contacting the KEPCA API, enabling offline verification.

Format

base64url(header).base64url(payload).base64url(signature)
json
{
  "alg": "HS256",
  "v": 1
}

Payload

json
{
  "sk": "mpt_site_abc123",
  "ts": 1712700000,
  "exp": 1712700120,
  "rs": 0.15,
  "ch": "pow",
  "ip": "sha256_of_client_ip",
  "jti": "unique_token_id"
}
FieldDescription
skSite key the token was issued for
tsIssued-at timestamp (Unix seconds)
expExpiry timestamp (120 seconds after issue)
rsRisk score at time of issue (0.0 - 1.0)
chChallenge type that was solved
ipSHA-256 hash of the client IP (privacy-safe)
jtiUnique token ID for replay prevention

Offline verification

Because the token is self-contained, your backend can verify it locally using the shared HMAC secret without making a network call to KEPCA. The POST /v1/siteverify endpoint does the same thing but also logs analytics events.

KVKK/GDPR Uyumlu — Verileriniz yurt icinde kalir.