# Detect Plagiarism in Text

> A comprehensive guide to using the Copyleaks Plagiarism Checker API for robust originality verification.

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

<Steps>
  <Step>
    ### 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](https://api.copyleaks.com/signup)**.
    - You can find your API key on the **[API Dashboard](https://api.copyleaks.com/dashboard)**.
  </Step>

  <Step>
    ### Installation
    <InstallSDKs />
  </Step>

  <Step>
    ### Login
    <GuideLogin />
  </Step>

  <Step>
    ### Submit for scanning
    Use the [Submit File Endpoint](/reference/actions/authenticity/submit-file) to send content for analysis. We suggest you provide a unique `scanId` for each submission.

    <Tip>
    For testing, set `"sandbox": true`. Sandbox mode is free and returns mock results.
    </Tip>
    
    <Note>
    **What is Base64 Encoding?**

    Base64 converts binary files into text strings so they can be sent via JSON. All programming languages have built-in Base64 encoding functions, see the code examples below for your language.
    </Note>
    
    <CodeGroup>
        ```http title="HTTP" icon="globe"
        PUT https://api.copyleaks.com/v3/scans/submit/file/my-plagiarism-scan

        Headers
        Authorization: Bearer <YOUR_AUTH_TOKEN>
        Content-Type: application/json

        Body
        {
            "base64": "SGVsbG8gd29ybGQh",
            "filename": "file.txt",
            "properties": {
                "webhooks": {
                  "status": "https://your-server.com/webhook/{STATUS}"
                  },
                "sandbox": true
            }
        }
        ```
      ```bash title="cURL" icon="terminal"
      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
                 }
               }'
      ```
      ```python title="Python" icon="python"
      import base64
      import random
      from copyleaks.copyleaks import Copyleaks
      from copyleaks.models.submit.document import FileDocument
      from copyleaks.models.submit.properties.scan_properties import ScanProperties
      from copyleaks.models.submit.properties.submit_webhooks import SubmitWebhooks

      print("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 id
      file_submission = FileDocument(BASE64_FILE_CONTENT, FILENAME)
      # Once the scan completes on Copyleaks servers, we will trigger a webhook that notifies you.
      # Provide your public endpoint server address. If you are testing 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 ScanProperties
      scan_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 scanning
      print("Sent to scanning")
      print("You will be notified, using your webhook, once the scan is completed.")
      ```
      ```javascript title="JavaScript" icon="square-js"
      const { Copyleaks, CopyleaksFileSubmissionModel } = require('plagiarism-checker');

      async function submitTextForPlagiarismCheck() {
          try {
              // Initialize Copyleaks
              const copyleaks = new Copyleaks();
              
              // Login to get the authentication token.
              // Replace with your email and API key.
              const loginResult = await copyleaks.loginAsync('YOUR_EMAIL@example.com', 'YOUR_API_KEY');

              const scanId = `text-plagiarism-scan-${Date.now()}`;
              const WEBHOOK_URL = "https://your-server.com/webhook";

              // The text to be checked for plagiarism
              const textContent = "Hello world, this is a test.";
              const base64Content = Buffer.from(textContent).toString('base64');

              // Create a submission model
              const submission = new CopyleaksFileSubmissionModel(
                  base64Content,
                  'sample.txt',
                  {
                      sandbox: true, // Use sandbox for testing
                      webhooks: {
                          // Copyleaks will notify this URL when the scan is complete.
                          status: `${WEBHOOK_URL}/{STATUS}`
                      }
                  }
              );

              // Submit the file for scanning
              await copyleaks.submitFileAsync(loginResult, scanId, submission);
              console.log(`Submission successful. Scan ID: ${scanId}`);

          } catch (error) {
              console.error("An error occurred:", error);
          }
      }

      submitTextForPlagiarismCheck();
      ```
      ```java title="Java" icon="java"
      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 webhooks
      SubmissionWebhooks webhooks = new SubmissionWebhooks("https://your-server.com/webhook/{STATUS}");
      webhooks.setNewResult("https://your-server.com/webhook/new-results");

      // Create submission properties
      SubmissionProperties 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 detection
      properties.setSensitivityLevel(3); // 1-5, where 5 is most sensitive

      // Create and submit the file
      CopyleaksFileSubmissionModel submission = new CopyleaksFileSubmissionModel(base64Content, "file.txt", properties);

      Copyleaks.submitFile(authToken, scanId, submission);
      System.out.println("Sent to scanning...");
      ```
    </CodeGroup>
  </Step>

  <Step>
    ### Wait for the completion webhook
    The scan can take some time. Once it's complete, Copyleaks will send a [completed webhook](/reference/data-types/authenticity/webhooks/scan-completed) to the status URL you provided. This webhook contains a summary of the scan results, including any `result` IDs for found plagiarism matches.
  </Step>

  <Step>
    ### Export detailed results
    After the `completed` webhook arrives, use the [export endpoint](/reference/actions/downloads/export) to retrieve the detailed plagiarism [`results`](/reference/data-types/authenticity/results/new-plagiarism-result) using the `result` 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.

    <CodeGroup>
        ```http title="HTTP" icon="globe"
        POST https://api.copyleaks.com/v3/downloads/my-plagiarism-scan/export/<export_id>

        Headers
        Authorization: Bearer <your_token>
        Content-Type: application/json

        Body
        {
            "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"
                        ]
                    ]
                }
            ]
        }
        ```
      ```bash title="cURL" icon="terminal"
      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"
                        }
                    }
                ]
              }'
      ```
      ```python title="Python" icon="python"
      from copyleaks.copyleaks import Copyleaks
      from copyleaks.models.export import Export, ExportResult

      export_id = "my-export-1"
      export = Export()
      export.set_completion_webhook('https://your-server.com/webhook/export/completion')

      # Export a specific plagiarism result
      result1 = ExportResult()
      result1.set_id('<RESULT_ID_FROM_COMPLETED_WEBHOOK>')
      result1.set_endpoint('https://your-server.com/webhook/export/result/1')  # Only URL
      result1.set_verb('POST')  # HTTP method separately
      export.set_results([result1])

      Copyleaks.export(auth_token, scan_id, export_id, export)
      print("Export initiated.")
      ```
      ```javascript title="JavaScript" icon="square-js"
        const { Copyleaks, CopyleaksExportModel } = require('plagiarism-checker');

        async function exportPlagiarismResults() {
            try {
                // Initialize Copyleaks
                const copyleaks = new Copyleaks();

                // Login to get the authentication token.
                // Replace with your email and API key.
                const loginResult = await copyleaks.loginAsync('YOUR_EMAIL@example.com', 'YOUR_API_KEY');

                const scanId = "YOUR_SCAN_ID"; // The ID of the scan you want to export
                const exportId = `export-${scanId}-${Date.now()}`;
                const WEBHOOK_URL = "https://your-server.com/webhook";
                
                // The result IDs to export, obtained from the completion webhook
                const 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 model
                const exportModel = new CopyleaksExportModel(
                    `${WEBHOOK_URL}/export/${exportId}/completion`, // Completion webhook URL
                    results,
                    {
                        // Request to export the crawled version of the original document
                        endpoint: `${WEBHOOK_URL}/export/${exportId}/crawled-version`,
                        verb: "POST"
                    }
                );

                // Start the export process
                await copyleaks.exportAsync(loginResult, scanId, exportId, exportModel);
                console.log(`Export initiated. Export ID: ${exportId}`);

            } catch (error) {
                console.error("An error occurred:", error);
            }
        }

        exportPlagiarismResults();
      ```
        ```java title="Java" icon="java"
            import classes.Copyleaks;
            import models.exports.*;

            String scanId = "2a1b402420"; // Your scan ID from submission
            String exportId = "08338e505d"; // Your chosen export ID

            // Create headers (optional)
            String[][] headers = new String[][]{
                new String[]{"key", "value"}, 
                new String[]{"key2", "value2"}
            };

            // Export specific plagiarism results
            ExportResults results = new ExportResults(
                "2a1b402420", // Result ID from completed webhook
                "https://your.server/webhook/export/result/2a1b402420", // Endpoint URL
                "POST", // HTTP method
                headers // Optional headers
            );

            // Create array of results to export
            ExportResults[] exportResultsArray = new ExportResults[1];
            exportResultsArray[0] = results;

            // Export crawled version of original document
            ExportCrawledVersion crawledVersion = new ExportCrawledVersion(
                "https://your.server/webhook/export/result/08338e505d",
                "POST",
                headers
            );

            // Create the export model
            CopyleaksExportModel exportModel = new CopyleaksExportModel(
                "https://your.server/webhook/export/result/2b42c39fba", // Completion webhook
                exportResultsArray, // Results to export
                crawledVersion // Crawled version
            );

            // Execute the export with comprehensive exception handling
            try {
                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();
            }
        ```
    </CodeGroup>
  </Step>

  <Step>
    ### Summary
    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.
  </Step>
</Steps>

## Next steps
<CardGroup cols={2}>
    <Card title="Webhooks Overview" icon="plug" href="/reference/data-types/authenticity/webhooks/overview/">Learn how to securely receive and process notifications from Copyleaks.</Card>
    <Card title="Viewing Scan Results" icon="browser" href="/concepts/features/how-to-display/">Understand the scan result format and how to display it to your users.</Card>
</CardGroup>
