nsfw.sptrnd.id
429 RATE_LIMITED with a Retry-After header (seconds until a slot frees up).RateLimit-Limit, RateLimit-Remaining and RateLimit-Reset headers.nsfw and normal, each response includes a confidence score on the chosen label.image or a raw body with Content-Type: image/*.label, is_nsfw and confidence.429 wait for Retry-After seconds.| Method & path | Description |
|---|---|
POST /v1/moderate | Multipart field image, or a raw body with Content-Type: image/*. Rate-limited. |
curl -X POST --data-binary @photo.jpg \ -H "Content-Type: image/jpeg" \ https://nsfw.sptrnd.id/v1/moderate
Or multipart: curl -F image=@photo.jpg https://nsfw.sptrnd.id/v1/moderate
const r = await fetch("https://nsfw.sptrnd.id/v1/moderate", {
method: "POST",
headers: { "Content-Type": "image/jpeg" },
body: file, // a File or Blob
});
const { result } = await r.json(); import requests
r = requests.post(
"https://nsfw.sptrnd.id/v1/moderate",
headers={"Content-Type": "image/jpeg"},
data=open("photo.jpg", "rb").read(),
)
print(r.json()["result"]["label"]) {
"request_id": "0192f0c4-...",
"image": { "sha256": "...", "size_bytes": 183422,
"mime": "image/jpeg", "width": 1024, "height": 768 },
"result": { "label": "nsfw", "is_nsfw": true, "confidence": 0.9871 }
} confidence is the certainty of the chosen label (4 decimals). Repeating the same image returns an identical body, just faster.
request_id | unique id for tracing; keep it when reporting an issue |
image.sha256 | hash of the uploaded file |
image.size_bytes, mime, width, height | what the server actually received and how it was read |
result.label | nsfw or normal |
result.is_nsfw | the moderation decision as a boolean |
result.confidence | certainty of the label, 0 to 1 |
All errors are returned as application/problem+json:
{ "error": { "code": "PAYLOAD_TOO_LARGE",
"message": "payload exceeds 10 MB", "request_id": "..." } } RATE_LIMITED | quota exceeded; wait Retry-After seconds, then retry |
PAYLOAD_TOO_LARGE | file is over 10 MB; compress or resize it |
UNSUPPORTED_MEDIA_TYPE | only JPEG, PNG and WebP are accepted |
IMAGE_TOO_LARGE | dimensions exceed 8000 px; downscale the image |
TIMEOUT, WORKER_UNAVAILABLE | service is busy; retry with backoff |
Other codes: INVALID_REQUEST · EMPTY_BODY · OVERLOADED · INTERNAL
429 or 503; retry politely using the Retry-After header.