curl --request POST \
--url https://api.bodyguard.ai/analyze/v1/image \
--header 'Authorization: <api-key>' \
--header 'Content-Type: application/json' \
--data '
{
"channelId": "<your-channel-id>",
"publishedAt": "2026-04-23T10:30:00.000Z",
"imageUrl": "https://cdn.example.com/uploads/photo.jpg"
}
'import requests
url = "https://api.bodyguard.ai/analyze/v1/image"
payload = {
"channelId": "<your-channel-id>",
"publishedAt": "2026-04-23T10:30:00.000Z",
"imageUrl": "https://cdn.example.com/uploads/photo.jpg"
}
headers = {
"Authorization": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
channelId: '<your-channel-id>',
publishedAt: '2026-04-23T10:30:00.000Z',
imageUrl: 'https://cdn.example.com/uploads/photo.jpg'
})
};
fetch('https://api.bodyguard.ai/analyze/v1/image', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.bodyguard.ai/analyze/v1/image",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'channelId' => '<your-channel-id>',
'publishedAt' => '2026-04-23T10:30:00.000Z',
'imageUrl' => 'https://cdn.example.com/uploads/photo.jpg'
]),
CURLOPT_HTTPHEADER => [
"Authorization: <api-key>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.bodyguard.ai/analyze/v1/image"
payload := strings.NewReader("{\n \"channelId\": \"<your-channel-id>\",\n \"publishedAt\": \"2026-04-23T10:30:00.000Z\",\n \"imageUrl\": \"https://cdn.example.com/uploads/photo.jpg\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.bodyguard.ai/analyze/v1/image")
.header("Authorization", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"channelId\": \"<your-channel-id>\",\n \"publishedAt\": \"2026-04-23T10:30:00.000Z\",\n \"imageUrl\": \"https://cdn.example.com/uploads/photo.jpg\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.bodyguard.ai/analyze/v1/image")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"channelId\": \"<your-channel-id>\",\n \"publishedAt\": \"2026-04-23T10:30:00.000Z\",\n \"imageUrl\": \"https://cdn.example.com/uploads/photo.jpg\"\n}"
response = http.request(request)
puts response.read_body{
"imageAnalysis": {
"classifications": [
"PARTIAL_NUDITY"
],
"classificationMeta": {
"PARTIAL_NUDITY": {
"confidenceScore": 0.92
}
},
"ocrAnalysis": {
"text": "Text extracted from the image",
"textAnalysis": {
"type": "HATEFUL",
"classifications": [
"INSULT"
],
"severity": "HIGH",
"directedAt": "AUTHOR_OF_COMMENT",
"language": "en",
"recommendedAction": "REMOVE",
"censoredText": "Einstein is an *******",
"classificationMeta": {
"INSULT": {
"severity": "MEDIUM"
}
}
}
}
}
}Analyze an image
Analyzes an image by URL or by inline image bytes. Returns a list of classifications for the image and, when OCR is enabled, the text extracted from the image along with its own text analysis.
Only PNG, JPEG and WebP images are accepted, and the image must not exceed 1 MiB (1,048,576 bytes). Requests with an unsupported format or an oversized image are rejected with a 400 Bad Request.
Before diving in, we recommend reading the image taxonomy to understand the classifications returned by this endpoint.
curl --request POST \
--url https://api.bodyguard.ai/analyze/v1/image \
--header 'Authorization: <api-key>' \
--header 'Content-Type: application/json' \
--data '
{
"channelId": "<your-channel-id>",
"publishedAt": "2026-04-23T10:30:00.000Z",
"imageUrl": "https://cdn.example.com/uploads/photo.jpg"
}
'import requests
url = "https://api.bodyguard.ai/analyze/v1/image"
payload = {
"channelId": "<your-channel-id>",
"publishedAt": "2026-04-23T10:30:00.000Z",
"imageUrl": "https://cdn.example.com/uploads/photo.jpg"
}
headers = {
"Authorization": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
channelId: '<your-channel-id>',
publishedAt: '2026-04-23T10:30:00.000Z',
imageUrl: 'https://cdn.example.com/uploads/photo.jpg'
})
};
fetch('https://api.bodyguard.ai/analyze/v1/image', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.bodyguard.ai/analyze/v1/image",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'channelId' => '<your-channel-id>',
'publishedAt' => '2026-04-23T10:30:00.000Z',
'imageUrl' => 'https://cdn.example.com/uploads/photo.jpg'
]),
CURLOPT_HTTPHEADER => [
"Authorization: <api-key>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.bodyguard.ai/analyze/v1/image"
payload := strings.NewReader("{\n \"channelId\": \"<your-channel-id>\",\n \"publishedAt\": \"2026-04-23T10:30:00.000Z\",\n \"imageUrl\": \"https://cdn.example.com/uploads/photo.jpg\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.bodyguard.ai/analyze/v1/image")
.header("Authorization", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"channelId\": \"<your-channel-id>\",\n \"publishedAt\": \"2026-04-23T10:30:00.000Z\",\n \"imageUrl\": \"https://cdn.example.com/uploads/photo.jpg\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.bodyguard.ai/analyze/v1/image")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"channelId\": \"<your-channel-id>\",\n \"publishedAt\": \"2026-04-23T10:30:00.000Z\",\n \"imageUrl\": \"https://cdn.example.com/uploads/photo.jpg\"\n}"
response = http.request(request)
puts response.read_body{
"imageAnalysis": {
"classifications": [
"PARTIAL_NUDITY"
],
"classificationMeta": {
"PARTIAL_NUDITY": {
"confidenceScore": 0.92
}
},
"ocrAnalysis": {
"text": "Text extracted from the image",
"textAnalysis": {
"type": "HATEFUL",
"classifications": [
"INSULT"
],
"severity": "HIGH",
"directedAt": "AUTHOR_OF_COMMENT",
"language": "en",
"recommendedAction": "REMOVE",
"censoredText": "Einstein is an *******",
"classificationMeta": {
"INSULT": {
"severity": "MEDIUM"
}
}
}
}
}
}Authorizations
API key authentication. Provide your key in the Authorization
header with the ApiKey scheme:
Authorization: ApiKey <your-api-key>
Body
- Option 1
- Option 2
Public URL of the image to analyze. The image must be a PNG, JPEG or WebP file no larger than 1 MiB. Only one of imageUrl or imageData can be provided.
When fetching the image, Bodyguard sends the user-agent Bodyguard-Analyze/1.0 (+https://bodyguard.ai/bot). If you allowlist Bodyguard on a CDN or firewall, match on the stable Bodyguard-Analyze product token rather than the full string — the version number and bot URL may change over time. Image fetches are not sent from a fixed set of IP addresses, so the user-agent is the signal to allowlist against.
Publication date of the image.
Base64-encoded image bytes. The image must be a PNG, JPEG or WebP file no larger than 1 MiB. Only one of imageUrl or imageData can be provided.
Response
Analysis completed.
Moderation result for an image.
Show child attributes
Show child attributes