Detect AI-Generated Videos
The Copyleaks AI Video Detection API analyzes whether a video was generated or partially generated by AI. This API is asynchronous — you submit a video URL, and Copyleaks notifies your server via webhook when the results are ready.
This guide walks you through submitting a video for AI detection and interpreting the webhook response.
🚀 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"}Save this token! It’s valid for 48 hours and can be reused for subsequent API calls.
-
Submit a Video for Analysis
Section titled “Submit a Video for Analysis”Use the AI Video Detector Endpoint to submit a video URL for analysis. Provide a unique
scanIdfor each submission and a webhook URL to receive the results.Providing a Video URL
Section titled “Providing a Video URL”The API requires a publicly accessible URL pointing to your video file — Copyleaks will fetch it directly. The video must be reachable at the time of processing, so avoid URLs that expire before the scan completes.
A common approach is to upload the video to a cloud storage service and generate a pre-signed URL:
- Amazon S3 — Upload the file to an S3 bucket and generate a pre-signed URL with a sufficient expiry window (e.g. 1 hour). The bucket does not need to be public.
- Google Cloud Storage — Upload to a GCS bucket and create a signed URL using the GCS console or SDK.
- Azure Blob Storage — Upload to a container and generate a SAS URL with read access.
- Any CDN or file host — Any URL that returns the raw video file with a
Content-Typevideo header works.
Setting Up Your Webhook
Section titled “Setting Up Your Webhook”The
webhooks.urlfield is where Copyleaks willPOSTthe detection results when processing is done. This must be a publicly reachable HTTPS endpoint on your server.A few tips for getting started:
- During development — Use a tool like ngrok or webhook.site to expose a local server or inspect incoming payloads without writing any backend code.
- In production — Implement a route in your API (e.g.
POST /webhook/video-results) that receives the payload, validates it, and stores or acts on the results. - Security — Use the optional
webhooks.headersfield to pass a secret token with the webhook request, which your server can verify to ensure the request is coming from Copyleaks.
Video Requirements
Section titled “Video Requirements”Returned as
400 Bad Requestat submit (synchronous):- Missing or invalid
scanId,filename,url,model, orwebhooks - Unsupported file extension (supported:
.mp4,.avi,.mov,.mkv,.webm,.flv,.wmv,.mpg,.m4v,.3gp,.mxf) - Filename longer than 255 characters
- Invalid
verbvalue
Delivered to your webhook as an error result (asynchronous, after download):
- Duration outside 2 seconds–1 hour →
video_too_short(67) /video_too_long(68) - File larger than 512 MiB →
file_too_large(6) - Resolution below 360×360 →
video_resolution_too_low(65) - Frame rate below 16 FPS →
fps_too_low(66) - Undecodable codec →
unsupported_video_codec(71) - Corrupt or truncated file →
video_truncated(70) - Generic decode failure →
video_load_failed(72)
POST https://api.copyleaks.com/v1/ai-video-detector/my-video-scan-1/submitHeadersAuthorization: Bearer <YOUR_AUTH_TOKEN>Content-Type: application/jsonBody{"url": "https://example.com/my-video.mp4","filename": "my-video.mp4","model": "ai-video-1-pro","sandbox": true,"webhooks": {"url": "https://your-server.com/webhook/receive-results"}}Terminal window curl -X POST "https://api.copyleaks.com/v1/ai-video-detector/my-video-scan-1/submit" \-H "Authorization: Bearer <YOUR_AUTH_TOKEN>" \-H "Content-Type: application/json" \-d '{"url": "https://example.com/my-video.mp4","filename": "my-video.mp4","model": "ai-video-1-pro","sandbox": true,"webhooks": {"url": "https://your-server.com/webhook/receive-results"}}'import requestsurl = 'https://api.copyleaks.com/v1/ai-video-detector/my-video-scan-1/submit'headers = {'Authorization': 'Bearer YOUR_LOGIN_TOKEN','Content-Type': 'application/json'}payload = {'url': 'https://example.com/my-video.mp4','filename': 'my-video.mp4','model': 'ai-video-1-pro','sandbox': True,'webhooks': {'url': 'https://your-server.com/webhook/receive-results'}}response = requests.post(url, json=payload, headers=headers)print(f"Submission status: {response.status_code}") # Expect 201 Createdconst response = await fetch('https://api.copyleaks.com/v1/ai-video-detector/my-video-scan-1/submit',{method: 'POST',headers: {'Authorization': 'Bearer YOUR_LOGIN_TOKEN','Content-Type': 'application/json'},body: JSON.stringify({url: 'https://example.com/my-video.mp4',filename: 'my-video.mp4',model: 'ai-video-1-pro',sandbox: true,webhooks: {url: 'https://your-server.com/webhook/receive-results'}})});console.log('Submission status:', response.status); // Expect 201 Created -
Receive the Webhook Result
Section titled “Receive the Webhook Result”Once Copyleaks finishes analyzing the video, it sends a POST request to your webhook URL with the detection results.
Example Webhook Payload
Section titled “Example Webhook Payload”{"model": "ai-video-1-pro","audioResult": {"starts": [13000, 45000, 47000],"lengths": [14000, 1000, 8700],"exclude": {"starts": [0, 3250, 5400, 7600, 10500],"lengths": [2950, 1500, 1200, 650, 1050]}},"visualResult": {"starts": [11566, 29433],"lengths": [6134, 26267],"exclude": {"starts": [],"lengths": []}},"summary": {"audioAIRatio": 0.4902,"visualAIRatio": 0.5817,"overallAIRatio": 0.7487},"videoInfo": {"metadata": {"issuedTime": "2026-03-17T13:14:57+00:00","issuedBy": "OpenAI","appOrDeviceUsed": "Sora","contentSummary": "Created using generative AI"},"duration": 55.7},"scannedVideo": {"scanId": "my-video-scan-1","actualCredits": 1,"expectedCredits": 1,"creationTime": "2026-05-05T12:37:50Z"}}Understanding the Results
Section titled “Understanding the Results”The webhook response contains three key sections:
audioResultandvisualResult— Time-based detections for the audio and visual tracks, encoded as arrays of start positions (starts) and durations (lengths) in milliseconds.The
excludeobject within each result identifies segments that were not scored. These ranges are excluded because the content could not be meaningfully analyzed, and they are not counted in the AI ratio calculations.summary— Overall AI ratios. Segments listed inexcludeare not counted in any of these calculations:audioAIRatio— Ratio of AI-detected audio duration to total audible duration. Excluded audio ranges are not counted (0.0–1.0)visualAIRatio— Ratio of AI-detected visual duration to total visible duration. Excluded visual ranges are not counted (0.0–1.0)overallAIRatio— Combined AI ratio across both audio and visual tracks, relative to the total video duration (0.0–1.0)
videoInfo— Video duration and optional C2PA/embedded metadata identifying the generating tool.For a complete breakdown of all response fields, see the AI Video Detection Response documentation.
-
🎉 Congratulations!
Section titled “🎉 Congratulations!”You have successfully submitted a video for AI detection and received the webhook results. You can now use the
summary.overallAIRatioand the time-basedaudioResult/visualResultdata in your application.