Detect Plagiarism in Text
The Copyleaks Authenticity API is the most powerful way to analyze your content for plagiarism. This API is asynchronous - you submit a scan, and Copyleaks notifies your server via webhooks when the results are ready to be retrieved.
This guide will walk you through the process of submitting a scan, enabling plagiarism detection, and exporting 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 Scanning
Section titled “Submit for Scanning”Use the Submit File Endpoint to send content for analysis. We suggest you to provide a unique
scanId
for each submission.PUT https://api.copyleaks.com/v3/scans/submit/file/my-plagiarism-scanHeadersAuthorization: Bearer <YOUR_AUTH_TOKEN>Content-Type: application/jsonBody{"base64": "SGVsbG8gd29ybGQh","filename": "file.txt","properties": {"webhooks": {"status": "https://your-server.com/webhook/{STATUS}"},"sandbox": true}}Terminal window curl -X PUT "https://api.copyleaks.com/v3/scans/submit/file/my-plagiarism-scan" \-H "Authorization: Bearer <YOUR_AUTH_TOKEN>" \-H "Content-Type: application/json" \-d '{"base64": "SGVsbG8gd29ybGQh","filename": "file.txt","properties": {"webhooks": {"status": "https://your-server.com/webhook/{STATUS}"},"sandbox": true,"scanning": {"internet": true,},"cheatDetection": false,}}'import base64import randomfrom copyleaks.copyleaks import Copyleaksfrom copyleaks.models.submit.document import FileDocumentfrom copyleaks.models.submit.properties.scan_properties import ScanPropertiesfrom copyleaks.models.submit.properties.submit_webhooks import SubmitWebhooksprint("Submitting a new file...")BASE64_FILE_CONTENT = base64.b64encode(b'Hello world').decode('utf8') # or read your file and convert it into BASE64 presentation.FILENAME = "hello.txt"scan_id = random.randint(100, 100000) # generate a random scan idfile_submission = FileDocument(BASE64_FILE_CONTENT, FILENAME)# Once the scan completed on Copyleaks servers, we will trigger a webhook that notify you.# Write your public endpoint server address. If you testing it locally, make sure that this endpoint# is publicly available.webhooks = SubmitWebhooks()webhooks.set_status('https://your.server/webhook/{STATUS}')webhooks.set_new_result('https://your.server/webhook/new-results')# Pass the webhooks to ScanPropertiesscan_properties = ScanProperties(status_webhook='https://your.server/webhook/{STATUS}')scan_properties.set_webhooks(webhooks)scan_properties.set_sandbox(True) # Turn on sandbox mode. Turn off on production.file_submission.set_properties(scan_properties)Copyleaks.submit_file(auth_token, scan_id, file_submission) # sending the submission to scanningprint("Send to scanning")print("You will notify, using your webhook, once the scan was completed.")const { Copyleaks, CopyleaksFileSubmissionModel } = require('plagiarism-checker');async function submitTextForPlagiarismCheck() {try {// Initialize Copyleaksconst copyleaks = new Copyleaks();// Login to get the authentication token.// Replace with your email and API key.const scanId = `text-plagiarism-scan-${Date.now()}`;const WEBHOOK_URL = "https://your-server.com/webhook";// The text to be checked for plagiarismconst textContent = "Hello world, this is a test.";const base64Content = Buffer.from(textContent).toString('base64');// Create a submission modelconst submission = new CopyleaksFileSubmissionModel(base64Content,'sample.txt',{sandbox: true, // Use sandbox for testingwebhooks: {// Copyleaks will notify this URL when the scan is complete.status: `${WEBHOOK_URL}/{STATUS}`}});// Submit the file for scanningawait copyleaks.submitFileAsync(loginResult, scanId, submission);console.log(`Submission successful. Scan ID: ${scanId}`);} catch (error) {console.error("An error occurred:", error);}}submitTextForPlagiarismCheck();import classes.Copyleaks;import models.submissions.CopyleaksFileSubmissionModel;import models.submissions.properties.*;import java.util.Base64;import java.nio.charset.StandardCharsets;String scanId = "my-plagiarism-scan";String base64Content = Base64.getEncoder().encodeToString("Hello world".getBytes(StandardCharsets.UTF_8));// Configure webhooksSubmissionWebhooks webhooks = new SubmissionWebhooks("https://your-server.com/webhook/{STATUS}");webhooks.setNewResult("https://your-server.com/webhook/new-results");// Create submission propertiesSubmissionProperties properties = new SubmissionProperties(webhooks);properties.setSandbox(true);// Configure indexing (this enables plagiarism detection)SubmissionIndexing indexing = new SubmissionIndexing();indexing.setCopyleaksDb(true);properties.setIndexing(indexing);// Set action to scan (plagiarism is enabled by default)properties.setAction(SubmissionActions.Scan);// Optional: Set sensitivity level for plagiarism detectionproperties.setSensitivityLevel(3); // 1-5, where 5 is most sensitive// Create and submit the fileCopyleaksFileSubmissionModel submission = new CopyleaksFileSubmissionModel(base64Content, "file.txt", properties);Copyleaks.submitFile(authToken, scanId, submission);System.out.println("Sent to scanning..."); -
Wait for Completion Webhook
Section titled “Wait for Completion Webhook”The scan can take some time. Once it’s complete, Copyleaks will send a completed webhook to the status URL you provided. This webhook contains a summary of the scan results, including any
result
IDs for found plagiarism matches. -
Export Detailed Results
Section titled “Export Detailed Results”After the
completed
webhook arrives, use the export endpoint to retrieve the detailed plagiarismresults
using theresult
IDs you received in the completion webhook.We will also export the Crawled Version. The
crawledVersion
webhook contains the text and html version of the document. This can later be used in order to display the report.In addition, you should also specify a
completionWebhook
to receive notifications when the export is ready.POST https://api.copyleaks.com/v3/downloads/my-plagiarism-scan/export/<export_id>HeadersAuthorization: Bearer <your_token>Content-Type: application/jsonBody{"completionWebhook": "https://your.server/export/completed","maxRetries": 3,"developerPayload": "custom_data_identifier","crawledVersion": {"endpoint": "https://your.server/webhook/export/crawled","verb": "POST","headers": [["header-key","header-value"]]},"results": [{"id": "result-1","endpoint": "https://your.server/webhook/export/result/result-1","verb": "POST","headers": [["header-key","header-value"]]}]}Terminal window curl -X POST "https://api.copyleaks.com/v3/downloads/my-plagiarism-scan/export/my-export-1" \-H "Authorization: Bearer <YOUR_AUTH_TOKEN>" \-H "Content-Type: application/json" \-d '{"completionWebhook": "https://your-server.com/webhook/export/completion","maxRetries": 3,"developerPayload": "custom_data_identifier","crawledVersion": {"endpoint": "https://your-server.com/webhook/export/crawled","verb": "POST","headers": {"header-key": "header-value","header-key-2": "header-value-2"}},"results": [{"id": "<RESULT_ID_FROM_COMPLETED_WEBHOOK>","endpoint": "https://your-server.com/webhook/export/result/1","verb": "POST","headers": {"header-key": "header-value"}}]}'from copyleaks.copyleaks import Copyleaksfrom copyleaks.models.export import Export, ExportResultexport_id = "my-export-1"export = Export()export.set_completion_webhook('https://your-server.com/webhook/export/completion')# Export a specific plagiarism resultresult1 = ExportResult()result1.set_id('<RESULT_ID_FROM_COMPLETED_WEBHOOK>')result1.set_endpoint('https://your-server.com/webhook/export/result/1') # Only URLresult1.set_verb('POST') # HTTP method separatelyexport.set_results([result1])Copyleaks.export(auth_token, scan_id, export_id, export)print("Export initiated.")const { Copyleaks, CopyleaksExportModel } = require('plagiarism-checker');async function exportPlagiarismResults() {try {// Initialize Copyleaksconst copyleaks = new Copyleaks();// Login to get the authentication token.// Replace with your email and API key.const scanId = "YOUR_SCAN_ID"; // The ID of the scan you want to exportconst exportId = `export-${scanId}-${Date.now()}`;const WEBHOOK_URL = "https://your-server.com/webhook";// The result IDs to export, obtained from the completion webhookconst resultIdsToExport = ["RESULT_ID_1", "RESULT_ID_2"];const results = resultIdsToExport.map(resultId => ({id: resultId,endpoint: `${WEBHOOK_URL}/export/${exportId}/result/${resultId}`,verb: "POST"}));// Create an export modelconst exportModel = new CopyleaksExportModel(`${WEBHOOK_URL}/export/${exportId}/completion`, // Completion webhook URLresults,{// Request to export the crawled version of the original documentendpoint: `${WEBHOOK_URL}/export/${exportId}/crawled-version`,verb: "POST"});// Start the export processawait copyleaks.exportAsync(loginResult, scanId, exportId, exportModel);console.log(`Export initiated. Export ID: ${exportId}`);} catch (error) {console.error("An error occurred:", error);}}exportPlagiarismResults();import classes.Copyleaks;import models.exports.*;String scanId = "2a1b402420"; // Your scan ID from submissionString exportId = "08338e505d"; // Your chosen export ID// Create headers (optional)String[][] headers = new String[][]{new String[]{"key", "value"},new String[]{"key2", "value2"}};// Export specific plagiarism resultsExportResults results = new ExportResults("2a1b402420", // Result ID from completed webhook"https://your.server/webhook/export/result/2a1b402420", // Endpoint URL"POST", // HTTP methodheaders // Optional headers);// Create array of results to exportExportResults[] exportResultsArray = new ExportResults[1];exportResultsArray[0] = results;// Export crawled version of original documentExportCrawledVersion crawledVersion = new ExportCrawledVersion("https://your.server/webhook/export/result/08338e505d","POST",headers);// Create the export modelCopyleaksExportModel exportModel = new CopyleaksExportModel("https://your.server/webhook/export/result/2b42c39fba", // Completion webhookexportResultsArray, // Results to exportcrawledVersion // Crawled version);// Execute the export with comprehensive exception handlingtry {Copyleaks.export(token, scanId, exportId, exportModel);System.out.println("Export initiated successfully.");} catch (ParseException e) {System.out.println("Parse error: " + e.getMessage());e.printStackTrace();} catch (AuthExpiredException e) {System.out.println("Authentication expired: " + e.getMessage());e.printStackTrace();} catch (UnderMaintenanceException e) {System.out.println("Service under maintenance: " + e.getMessage());e.printStackTrace();} catch (RateLimitException e) {System.out.println("Rate limit exceeded: " + e.getMessage());e.printStackTrace();} catch (CommandException e) {System.out.println("Command error: " + e.getMessage());e.printStackTrace();} catch (ExecutionException e) {System.out.println("Execution error: " + e.getMessage());e.printStackTrace();} catch (InterruptedException e) {System.out.println("Process interrupted: " + e.getMessage());e.printStackTrace();} -
🎉Congratulations!
Section titled “🎉Congratulations!”You have successfully submitted a scan for plagiarism detection and exported the results. You can now handle the results in your application, display them to users, or take further actions based on the findings.