# Overview

This endpoint allows you to compare two screenshots and allows you to visually spot the difference between the two.

## Compare two screenshots

You can compare two screenshots asynchronously by creating a job.

### Request

See example

`POST /screenshot/diff`

json

```
{
  "baseImage": {
    "fileObject": "hyder/1.png"
  },
  "comparisonImage": {
    "fileObject": "hyder/2.png"
  }
}
```

### Response: On Success

The response will be a JSON object acknowledging your request was received and queued.

##### Condition: If everything is OK

##### Code: `202`

See example

json

```
{
  "id": "536ca23e-10b3-4eb4-9677-24e0b556a069",
  "createdAt": "2023-11-27T16:07:26.459Z",
  "updatedAt": "2023-11-27T16:07:26.459Z",
  "message": "Your Diff Image request has been successfully queued."
}
```

### Response: On Error(s)

##### Code: `500`

See example

json

```
{
  "status": "failed",
  "message": "The two images are not of the same size",
  "createdAt": "2023-06-20T11:55:39.594Z",
  "updatedAt": "2023-06-20T11:57:23.033Z"
}
```

##### Code: `422`

See example

json

```
{
  "errors": [
    "The responseType does not support this value"
  ]
}
```

### Supported Attributes

## List of optional attributes

| Option | Default value (if not specified) | description |
| --- | --- | --- |
| cloud.upload | s3 | Save images to Amazon S3 or Cloudflare R2 bucket |
| cloud.fileObject | e.g `/path/acme/light-arr.png` | Sets the path including file name of your screenshot |
| threshold | 0 | Matching threshold, ranges from 0 to 1. Smaller values make the comparison more sensitive. |

## Comparing Images of Different Format

You can compare screenshots of different file types: **PNG**, **JPG**, and **WEBP** regardless whether it is in `baseImage` or `comparisonImage`. However, comparing images with different formats can result in a high pixel difference count, even if the images look visually identical. This is due to differences in compression and encoding between formats.

#### Why does this happen?

1. **JPEG is a lossy format**: JPEG compression introduces small artifacts and color changes, even if the image looks the same to the human eye. These artifacts are not present in PNG, which is a lossless format. As a result, the raw pixel values in a JPEG will almost never exactly match the original PNG, even if they look identical visually.
2. **Image comparison is strict**: By default, the endpoint compares the exact RGBA values of each pixel. Even a tiny difference in color (e.g., (255,255,255) vs (254,255,255)) will count as a difference. With JPEG artifacts, there are often thousands of such tiny differences.
3. **Threshold parameter**: The `threshold` parameter controls how sensitive the comparison is to small differences. A threshold of 0 means "only count as different if the pixels are exactly the same." Increasing the threshold (e.g., 0.1, 0.2) will make the image comparison more tolerant to small differences, and the pixel diff count will go down.

#### Example: Comparing PNG and JPG

Only the words `World` and `Mars` are different.

**PNG:**

**JPG:**

Diff result with `threshold: 0`:

Diff result with `threshold: 2`:

#### How to handle this?

- If you want to compare PNG and JPEG: **Always use a nonzero threshold** (e.g., 0.1 or 0.2). Accept that some small differences are normal due to JPEG compression.
- For strict pixel-perfect comparison: **Only compare images in the same format** (PNG vs PNG, JPEG vs JPEG). Avoid comparing PNG to JPEG if you expect a zero-diff result.

#### Example Request with `threshold`

json

```
{
  "baseImage": {
    "fileObject": "hyder/1.png"
  },
  "comparisonImage": {
    "fileObject": "hyder/2.jpg"
  },
  "threshold": 0.2
}
```

#### Format Comparison Table

| Format Pair | diff (threshold=0) | diff (threshold=0.2) | Visual diff |
| --- | --- | --- | --- |
| PNG vs PNG | 0 | 0 | None |
| JPEG vs JPEG | 0 (if same file) | 0 | None |
| PNG vs JPEG | High | Lower, but not zero | None/Minor |
| JPG vs WEBP | High | Lower, but not zero | None/Minor |
| PNG vs WEBP | High | Lower, but not zero | None/Minor |

**In short:**

- PNG and JPEG (or WEBP) are not pixel-identical, even if they look the same.
- Use a threshold, or only compare same-format images for strict tests.

## Check progress of screenshot comparison

See example

`GET /screenshot/diff/:id`

json

```
{
  "status": "success",
  "pixelDifference": {
    "count": 1670,
    "percentage": 0.35
  },
  "url": "https://launchbrightlyf137-prod.s3.us-east-1.amazonaws.com/diff/hyder_1_hyder/2.png.png"
}
```

## Bulk Screenshot comparison

If you would like to compare more than just a pair of screenshots at a time. You can send an array of objects.

##### Request:

See example

`POST /screenshot/diff`

json

```
[
  {
    "baseImage": {
      "fileObject": "hyder/1xx.png"
    },
    "comparisonImage": {
      "fileObject": "hyder/2.png"
    }
  },
  {
    "baseImage": {
      "fileObject": "hyder/1.png"
    },
    "comparisonImage": {
      "fileObject": "hyder/2.png"
    }
  }
]
```

#### Response:

See example

json

```
{
  "id": "7c75dd41-12cb-429e-b11e-a2c98844b654",
  "message": "Your Diff Screenshot request has been successfully queued.",
  "data": [
    {
      "id": "d6efdfa1-eb32-48e3-b24e-611a893f2781",
      "createdAt": "2024-02-16T16:50:28.308Z",
      "updatedAt": "2024-02-16T16:50:28.308Z"
    },
    {
      "id": "2f108e61-cd46-4e3e-9a5d-deab7f6a63e8",
      "createdAt": "2024-02-16T16:50:30.103Z",
      "updatedAt": "2024-02-16T16:50:30.103Z"
    }
  ]
}
```

#### HTTP Status codes:

| HTTP Code | Description |
| --- | --- |
| 202 | The job was successfully created. |
| 403 | Validation-related errors |
| 500 | Any unhandled crash |

## Check the progress of the bulk transload operation

##### Response:

See example

`GET /screenshot/diff/:id`

json

```
{
  "summary": {
    "total": 2,
    "success": 1,
    "pending": 0,
    "failed": 1
  },
  "data": [
    {
      "id": "2f108e61-cd46-4e3e-9a5d-deab7f6a63e8",
      "jobId": "156b6acd-0562-41e1-8160-f45c78e8dd51",
      "status": "success",
      "baseImage": {
        "fileObject": "hyder/1.png"
      },
      "comparisonImage": {
        "fileObject": "hyder/2.png"
      },
      "url": "https://launchbrightlyf9ff5e67329842e1a3a8fc00d5a7569c145137-prod.s3.us-east-1.amazonaws.com/diff/hyder_1_hyder_2.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=AKIASH5PNXSCN5O7E7U2%2F20240216%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20240216T165142Z&X-Amz-Expires=3600&X-Amz-Signature=603280608b8c9a758700a662cb9bfde6965a9a5f1feb5c170ac66de5bb7eddee&X-Amz-SignedHeaders=host&x-id=GetObject",
      "pixelDifference": {
        "count": 1670,
        "percentage": 0.34900439703743336
      },
      "createdAt": "2024-02-16T16:50:30.103Z",
      "updatedAt": "2024-02-16T16:50:34.674Z"
    },
    {
      "id": "d6efdfa1-eb32-48e3-b24e-611a893f2781",
      "jobId": "156b6acd-0562-41e1-8160-f45c78e8dd51",
      "status": "failed",
      "baseImage": {
        "fileObject": "hyder/1xx.png"
      },
      "comparisonImage": {
        "fileObject": "hyder/2.png"
      },
      "error": "The specified key does not exist.",
      "createdAt": "2024-02-16T16:50:28.308Z",
      "updatedAt": "2024-02-16T16:50:33.654Z"
    }
  ]
}
```

### Percentage Field

The percentage field represents a float value between 0 and 100, indicating the proportion of pixels changed relative to the whole image.

**Calculation Example:**

Consider an image with dimensions 1200px by 1200px. If there is a difference of 4958 pixels, the percentage difference is calculated as follows:

Percentage difference = (4958 / (1200 * 1200)) * 100 = 0.344%

In this example, the percentage difference of 0.344% reflects the pixel difference in relation to the total number of pixels in the image.

### Job Statuses:

| Status | Description |
| --- | --- |
| completed | The screenshot diff job was successful. |
| failed | An error occurred. See `error` field for details. |
| pending | The screenshot diff job has not yet been processed. |

### HTTP Status codes:

| HTTP Code | Description |
| --- | --- |
| 200 | On success |
| 500 | Any unhandled crash |

## Limitation of sending bulk requests

The API allows you to submit up to 100 screenshot diff jobs in a single request. If you have more than 100 jobs, you will need to send multiple requests.

To check the progress of multiple job IDs, separate them with commas, as shown below:

```
GET /screenshot/diff/:jobId1,: jobId2,: jobId3
```
