Detect AI-Generated Images
The Copyleaks AI Image Detection API is a powerful tool to determine if a given image was generated or partially generated by an AI. The API is synchronous, meaning you get the results in the same API call.
This guide will walk you through the process of submitting an image for AI detection and understanding the results.
🚀 Get Started
Section titled “🚀 Get Started”-
Before you begin
Section titled “Before you begin”Before you start, ensure you have the following:
- An active Copyleaks account. If you don’t have one, sign up for free.
- You can find your API key on the API Dashboard.
-
Installation
Section titled “Installation”Choose your preferred method for making API calls.
You can interact with the API using any standard HTTP client.
For a quicker setup, we provide a Postman collection. See our Postman guide for instructions.
Terminal window sudo apt-get install curlDownload it from curl.se
Terminal window brew install curlTerminal window pip install copyleaksTerminal window npm install plagiarism-checker -
To perform a scan, we first need to generate an access token. For that, we will use the login endpoint. The API key can be found on the Copyleaks API Dashboard.
Upon successful authentication, you will receive a token that must be attached to subsequent API calls via the Authorization: Bearer
<TOKEN>
header. This token remains valid for 48 hours.POST https://id.copyleaks.com/v3/account/login/apiHeadersContent-Type: application/jsonBody{"key": "00000000-0000-0000-0000-000000000000"}Terminal window export COPYLEAKS_API_KEY="your-api-key-here"curl --request POST \--url https://id.copyleaks.com/v3/account/login/api \--header 'Accept: application/json' \--header 'Content-Type: application/json' \--data "{\"email\": \"${COPYLEAKS_EMAIL}\",\"key\": \"${COPYLEAKS_API_KEY}\"}"from copyleaks.copyleaks import CopyleaksAPI_KEY = "your-api-key-here"# Login to Copyleaksauth_token = Copyleaks.login(EMAIL_ADDRESS, API_KEY)print("Logged successfully!\nToken:", auth_token)const { Copyleaks } = require("plagiarism-checker");const API_KEY = "your-api-key-here";const copyleaks = new Copyleaks();// Login functionfunction loginToCopyleaks() {return copyleaks.loginAsync(EMAIL_ADDRESS, API_KEY).then((loginResult) => {console.log("Login successful!");console.log("Access Token:", loginResult.access_token);return loginResult;},(err) => {console.error('Login failed:', err);throw err;});}loginToCopyleaks();import com.copyleaks.sdk.api.Copyleaks;String API_KEY = "00000000-0000-0000-0000-000000000000";// Login to Copyleakstry {String authToken = Copyleaks.login(EMAIL_ADDRESS, API_KEY);System.out.println("Logged successfully!\nToken: " + authToken);} catch (CommandException e) {System.out.println("Failed to login: " + e.getMessage());System.exit(1);}Response
{"access_token": "<ACCESS_TOKEN>",".issued": "2025-07-31T10:19:40.0690015Z",".expires": "2025-08-02T10:19:40.0690016Z"} -
Submit for Analysis
Section titled “Submit for Analysis”Use the AI Image Detector Endpoint to send an image for analysis. We suggest you to provide a unique
scanId
for each submission.POST https://api.copyleaks.com/v1/ai-image-detector/my-image-scan-1/checkHeadersAuthorization: Bearer <YOUR_AUTH_TOKEN>Content-Type: application/jsonBody{"base64": "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJ...","filename": "test-image.png","sandbox": true,"model": "ai-image-1-ultra"}Terminal window curl -X POST "https://api.copyleaks.com/v1/ai-image-detector/my-image-scan-1/check" \-H "Authorization: Bearer <YOUR_AUTH_TOKEN>" \-H "Content-Type: application/json" \-d '{"base64": "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJ...","filename": "test-image.png","sandbox": true,"model": "ai-image-1-ultra"}'import base64import requests# Read and encode the imagewith open('test-image.png', 'rb') as image_file:base64_image = base64.b64encode(image_file.read()).decode('utf-8')# Prepare the requesturl = 'https://api.copyleaks.com/v1/ai-image-detector/my-image-scan-1/check'headers = {'Authorization': 'Bearer YOUR_LOGIN_TOKEN','Content-Type': 'application/json'}payload = {'base64': base64_image,'filename': 'test-image.png','sandbox': True,'model': 'ai-image-1-ultra'}# Send the requestresponse = requests.post(url, json=payload, headers=headers)result = response.json()print(f"AI Detection Summary: {result['summary']}")const imageFile = document.getElementById('fileInput').files[0];const reader = new FileReader();reader.onload = async function(e) {const base64Data = e.target.result.split(',')[1];const response = await fetch('https://api.copyleaks.com/v1/ai-image-detector/my-image-scan-1/check', {method: 'POST',headers: {'Authorization': 'Bearer YOUR_LOGIN_TOKEN','Content-Type': 'application/json'},body: JSON.stringify({base64: base64Data,filename: imageFile.name,sandbox: true,model: 'ai-image-1-ultra'})});const result = await response.json();console.log('AI Detection Result:', result);};reader.readAsDataURL(imageFile);import java.io.IOException;import java.net.URI;import java.net.http.HttpClient;import java.net.http.HttpRequest;import java.net.http.HttpResponse;import java.nio.file.Files;import java.nio.file.Paths;import java.util.Base64;public class AiImageDetection {public static void main(String[] args) throws IOException, InterruptedException {String authToken = "YOUR_LOGIN_TOKEN";String imagePath = "path/to/your/test-image.png";String scanId = "my-java-scan-1";byte[] imageBytes = Files.readAllBytes(Paths.get(imagePath));String base64Image = Base64.getEncoder().encodeToString(imageBytes);// Using a simple String.format for the JSON payload.// For more complex scenarios, a JSON library like Gson or Jackson is recommended.String jsonPayload = String.format("{\"base64\": \"%s\", \"filename\": \"test-image.png\", \"sandbox\": true, \"model\": \"ai-image-1-ultra\"}",base64Image);HttpClient client = HttpClient.newHttpClient();HttpRequest request = HttpRequest.newBuilder().uri(URI.create("https://api.copyleaks.com/v1/ai-image-detector/" + scanId + "/check")).header("Authorization", "Bearer " + authToken).header("Content-Type", "application/json").POST(HttpRequest.BodyPublishers.ofString(jsonPayload)).build();HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());System.out.println("Status Code: " + response.statusCode());System.out.println("Response Body: " + response.body());}} -
Interpreting The Response
Section titled “Interpreting The Response”The API response contains a
summary
object with the overall percentage of AI vs. human pixels, and aresult
object with a Run-Length Encoded (RLE) mask.Understanding the RLE Mask
Section titled “Understanding the RLE Mask”Run-Length Encoding (RLE) is a compression method used to represent the AI-detected regions of the image efficiently. It provides an array of
starts
positions andlengths
for each run of AI-detected pixels in a flattened 1D version of the image.You can decode this RLE data to create a binary mask. Here’s a helper function to do so:
function decodeMask(rleData, imageWidth, imageHeight) {const totalPixels = imageWidth * imageHeight;const mask = new Array(totalPixels).fill(0);const starts = rleData.starts || [];const lengths = rleData.lengths || [];for (let i = 0; i < starts.length; i++) {const start = starts[i];const length = lengths[i];for (let j = 0; j < length; j++) {const position = start + j;if (position < totalPixels) {mask[position] = 1;}}}return mask;}// Example usage:// const { result, imageInfo } = await response.json();// const binaryMask = decodeMask(result, imageInfo.shape.width, imageInfo.shape.height);The resulting
binaryMask
is a 1D array where a1
represents an AI-detected pixel. You can use this mask to create a visual overlay on the original image.Creating a Visual Overlay
Section titled “Creating a Visual Overlay”After decoding the RLE data, you can use the resulting mask to draw a semi-transparent overlay on the original image. Here are some examples of how to achieve this:
# Requires: pip install Pillowfrom PIL import Imageimport iodef apply_overlay(image_bytes, rle_mask, width, height):"""Applies a red overlay to an image based on an RLE mask."""img = Image.open(io.BytesIO(image_bytes)).convert("RGBA")overlay = Image.new('RGBA', img.size, (255, 255, 255, 0))draw = Image.Draw.Draw(overlay)starts = rle_mask.get('starts', [])lengths = rle_mask.get('lengths', [])for i in range(len(starts)):start_pixel = starts[i]run_length = lengths[i]for p in range(run_length):pixel_index = start_pixel + px = pixel_index % widthy = pixel_index // widthif x < width and y < height:draw.point((x, y), fill=(255, 0, 0, 128))img = Image.alpha_composite(img, overlay)byte_arr = io.BytesIO()img.save(byte_arr, format='PNG')return byte_arr.getvalue()// Assumes 'decodeMask' function from above is availablefunction createOverlay(imageElement, rleData, color = 'rgba(255, 0, 0, 0.5)') {const canvas = document.createElement('canvas');const ctx = canvas.getContext('2d');const width = imageElement.width;const height = imageElement.height;canvas.width = width;canvas.height = height;ctx.drawImage(imageElement, 0, 0);const mask = decodeMask(rleData, width, height);ctx.fillStyle = color;for (let i = 0; i < mask.length; i++) {if (mask[i] === 1) {const x = i % width;const y = Math.floor(i / width);ctx.fillRect(x, y, 1, 1);}}return canvas; // Returns a canvas element with the overlay}import java.awt.Color;import java.awt.Graphics2D;import java.awt.image.BufferedImage;import java.io.ByteArrayInputStream;import java.io.ByteArrayOutputStream;import java.io.IOException;import javax.imageio.ImageIO;// Assumes a record for the RLE data, e.g.:// public record RleMask(int[] starts, int[] lengths) {}public class ImageOverlay {public static byte[] applyOverlay(byte[] imageBytes, RleMask rleMask, int width, int height) throws IOException {BufferedImage image = ImageIO.read(new ByteArrayInputStream(imageBytes));Graphics2D g = image.createGraphics();g.setColor(new Color(255, 0, 0, 128)); // Red with 50% opacityif (rleMask != null && rleMask.starts() != null) {for (int i = 0; i < rleMask.starts().length; i++) {int start = rleMask.starts()[i];int length = rleMask.lengths()[i];for (int j = 0; j < length; j++) {int pos = start + j;int x = pos % width;int y = pos / width;g.fillRect(x, y, 1, 1);}}}g.dispose();ByteArrayOutputStream baos = new ByteArrayOutputStream();ImageIO.write(image, "png", baos);return baos.toByteArray();}}For a complete breakdown of all fields in the response, see the AI Image Detection Response documentation.
-
🎉Congratulations!
Section titled “🎉Congratulations!”You have successfully submitted an image for AI detection. You can now use the JSON response in your application to take further action based on the findings.