---
title: "Retry a page scan"
method: POST
path: "/scans/{id}/retry"
tags: ["Page scans"]
---

# Retry a page scan

`POST /scans/{id}/retry`

## Request

- Base URL: `https://www.iminify.com/api/v1`
- URL: `https://www.iminify.com/api/v1/scans/{id}/retry`
- Auth: HTTP bearer

Queues a failed or cancelled scan again with the settings it had. It counts as a scan.

## Path parameters

- `id` string, uuid, required

## Response `202`

Queued. `Location` points at the new record.

- object
  - `data` Scan, required
    - `id` string, uuid, required: The scan's id.
    - `url` string, uri, required: The page that was scanned.
    - `status` 'queued' | 'scanning' | 'completed' | 'failed' | 'no-image-found' | 'cancelled', required
    - `note` string, nullable, required: What the scanner wrote when it finished: how many images it found and what became of each, or why it failed. `null` until then.
    - `settings` object, required: The settings every image the scan found is compressed with.
      - `level` 'none' | 'lossless' | 'ultra' | 'smart', required
      - `format` 'auto' | 'webp' | 'avif' | 'png' | 'jpg', required
      - `keep_metadata` boolean, required: Whether EXIF metadata is kept.
      - `width` integer, nullable, required: The width every image is resized to, or `null`.
      - `height` integer, nullable, required: The height every image is resized to, or `null`.
      - `scale` integer, nullable, required: The percentage every image is scaled to, or `null`.
    - `skipped` object[], required: Every image the scan found and did not compress, with why: `duplicate` (the same bytes as another address on the page, which was tried instead), `unsupported_format` (an SVG, say), `too_large`, `tracking_pixel`, `private_network`, `unreadable`, `unreachable` (the address failed to answer, or answered with an error), `refused` (it failed the checks every upload goes through) or `failed`. `message` says the same in a sentence. Images past your plan's per-scan limit or the scan's time budget were never fetched, so they are not listed; `note` counts them. Empty until the scan finishes.
      - `url` string, required
      - `reason` 'duplicate' | 'unsupported_format' | 'too_large' | 'tracking_pixel' | 'private_network' | 'unreadable' | 'unreachable' | 'refused' | 'failed', required: Why a page scan passed over an image it found on the page.
      - `message` string, required
    - `images_count` integer, required: How many images the scan queued.
    - `images_in_progress` integer, required: How many of them are still queued or being compressed. The scan is done once its status has ended and this is 0.
    - `alt_texts_in_progress` integer, required: How many finished images still have an AI alt text being written for the report's `suggested_alt`. They are written one at a time, so this can take a minute after `images_in_progress` reaches 0.
    - `images_finished` integer, required: How many of them have finished.
    - `original_size` integer, required: Bytes of the finished images before compression.
    - `optimized_size` integer, required: Bytes of the same images after compression.
    - `saved_bytes` integer, required: The difference between the two.
    - `saved_percent` number, nullable, required: The same saving as a percentage, or `null` while no image has finished.
    - `download_url` string, uri, required: Where to download every finished image as one zip.
    - `images` Image[]: The scan's images, newest first. Only on a single scan, not in a list.
      - `id` string, uuid, required: The image's id.
      - `status` 'queued' | 'optimizing' | 'completed' | 'failed' | 'already-optimized' | 'cancelled', required
      - `name` string, required: The name the optimized copy downloads under: the uploaded name, or the one you gave it, with the delivered format's extension. An `auto` conversion has no format until it finishes, so until then the extension is the uploaded file's own.
      - `original` object, required: The file as it was uploaded.
        - `name` string, required: The file name it downloads under.
        - `format` string, required: The file's format, as its extension: `jpg`, `png`, `webp`, `avif`, `gif`, `heic`, `tiff` and so on.
        - `size` integer, required: Its size in bytes.
        - `width` integer, required: Its width in pixels, the way it displays: a phone photo stored on its side is measured upright.
        - `height` integer, required: Its height in pixels, the way it displays.
        - `download_url` string, uri, required: Where to download it with your key.
      - `optimized` object, nullable, required: The optimized copy, or `null` until the image has finished.
        - `name` string, required: The file name it downloads under.
        - `format` string, required: The file's format, as its extension: `jpg`, `png`, `webp`, `avif`, `gif`, `heic`, `tiff` and so on.
        - `size` integer, required: Its size in bytes.
        - `width` integer, required: Its width in pixels, the way it displays: a phone photo stored on its side is measured upright.
        - `height` integer, required: Its height in pixels, the way it displays.
        - `download_url` string, uri, required: Where to download it with your key.
      - `saved_bytes` integer, nullable, required: Bytes the optimized copy saves against the original. Negative when a conversion or an enlargement made the file bigger. `null` until the image has finished.
      - `saved_percent` number, nullable, required: The same saving as a percentage of the original, to two decimal places. `null` until the image has finished.
      - `settings` object, required: The settings the image was compressed with, as they were sent.
        - `level` 'none' | 'lossless' | 'ultra' | 'smart', required
        - `format` 'auto' | 'webp' | 'avif' | 'png' | 'jpg', required
        - `keep_metadata` boolean, required: Whether the EXIF metadata was kept.
        - `width` integer, nullable, required: The width it was resized to, or `null`.
        - `height` integer, nullable, required: The height it was resized to, or `null`.
        - `scale` integer, nullable, required: The percentage it was scaled to, or `null`.
      - `alt_text` object, nullable, required: The AI alt text and suggested file name, or `null` when none was asked for. See [Alt text and file names](/docs/images#alt-text-and-file-names).
        - `status` 'pending' | 'written' | 'failed' | 'skipped', required: Where a result's AI alt text stands. `pending`: asked for and not written yet (only a finished result shows it as in progress; a failed compression keeps the request for its retry). `written`: the text and the suggested file name are stored. `failed`: the model refused, or the call or its thumbnail failed; it can be asked for again. `skipped`: asked for on a day whose alt texts were spent.
        - `text` string, nullable, required: One sentence for the image's `alt` attribute, or `null` until it is written.
        - `language` string, nullable, required: The language tag it was written in.
        - `suggested_name` string, nullable, required: A short descriptive file name without an extension, ready for the rename call, or `null` until it is written or when the model offered none.
      - `scan_id` string, uuid, nullable, required: The page scan that found the image, or `null` for an upload.
      - `source_url` string, uri, nullable, required: The address the image was fetched from: the image's address on the scanned page, or the `url` you sent instead of a file. `null` for a file you sent.
      - `share_url` string, uri, nullable, required: The public page while the image is shared, or `null`.
      - `created_at` string, date-time, required: When the image was queued.
      - `updated_at` string, date-time, required: When anything about it last changed, its status included.
    - `audit` ScanAudit
      - `rendered` boolean, required: Whether a browser opened the page. `false` when only its HTML could be read: then the image addresses are known and nothing about how they are shown, so every finding count is 0.
      - `images_found` integer, required: How many image addresses the page had. `images` lists them all unless a page had more than 1000.
      - `largest_paint` object, nullable, required: The page's largest contentful paint (LCP): the biggest thing in the first screen, which is when a visitor sees the page as loaded. `null` when it could not be measured.
        - `kind` 'image' | 'text' | 'none', required: `image` (a picture or a background), `text`, or `none` when the page painted nothing.
        - `element` string, nullable, required: The element's tag, such as `img`, `h1` or `div`.
        - `url` string, nullable, required: The image's address, when it is one. The image's own entry in `images` says `largest_paint: true`.
      - `findings` object, required: How many images have each finding.
        - `oversized` integer, required: Images whose file is more than twice as wide and twice as tall as the space they are shown in.
        - `without_dimensions` integer, required: Images shown without width and height attributes (and no CSS aspect ratio), so the page can move as they load.
        - `lazy_above_fold` integer, required: Images in the first screen that are lazy loaded, which delays them.
        - `eager_below_fold` integer, required: Images below the first screen that are not lazy loaded, so they load before they are needed.
        - `missing_alt` integer, required: Images without alt text. An empty `alt=""`, which marks an image as decorative, is not counted.
        - `lcp_not_prioritized` integer, required: 1 when the largest paint is an image without `fetchpriority="high"`, which would have the browser fetch it first.
      - `oversized_bytes` integer, required: About how many bytes the oversized images would shed if each were served at twice the size it is shown, the size a high density screen draws. An estimate from the share of pixels that would go.
      - `bytes` integer, required: The bytes a browser downloaded for the images listed.
      - `formats` object[], required: How many images arrived in each format, the commonest first, as a browser received them: a site can send a browser WebP or AVIF and the scan's own download the original format.
        - `format` string, required
        - `count` integer, required
      - `images` ScanAuditImage[], required: Every image address the page had, in the page's order.
        - `url` string, uri, required: The image's address on the page.
        - `format` string, nullable, required: The format a browser received it in (`jpg`, `png`, `webp`, `avif`, `gif`, `svg`, ...), or `null` when it did not load as an image.
        - `bytes` integer, nullable, required: The bytes a browser downloaded for it, or `null` when it did not load as an image.
        - `natural_width` integer, nullable, required: The file's own width in pixels, or `null` when it is not shown by an `img` element or did not load.
        - `natural_height` integer, nullable, required: The file's own height in pixels.
        - `rendered_width` integer, nullable, required: The width it is shown at on a desktop screen 1366 pixels wide, the largest where the page shows it more than once. `null` when no `img` element shows it (a CSS background, a hidden image).
        - `rendered_height` integer, nullable, required: The height it is shown at.
        - `above_fold` boolean, nullable, required: Whether it is in the first screen before scrolling, or `null` when that is not known.
        - `largest_paint` boolean, required: Whether it is the page's largest contentful paint.
        - `alt` 'missing' | 'empty' | 'present', required: What an image on a scanned page says to a screen reader. `missing`: no alt text at all, which is the finding. `empty`: alt="" (or marked decorative), which is right for an image that carries no meaning. `present`: it has a text alternative.
        - `findings` AuditFinding[], required: What is worth fixing about it, empty when nothing.
        - `wasted_bytes` integer, nullable, required: About how many bytes it would shed at twice the size it is shown, when it is oversized; otherwise `null`.
        - `outcome` 'compressed' | 'skipped' | 'left_out', required: What the scan did with it. `compressed`: it is one of the scan's images (`image_id`). `skipped`: passed over, with `skip_reason`; a `duplicate` names the image it shares its bytes with in `image_id`. `left_out`: never compressed, because the scan stopped at your plan's images per scan or its time budget, or the image has been deleted since.
        - `skip_reason` 'duplicate' | 'unsupported_format' | 'too_large' | 'tracking_pixel' | 'private_network' | 'unreadable' | 'unreachable' | 'refused' | 'failed', required: Why a page scan passed over an image it found on the page.
        - `image_id` string, uuid, nullable, required: The id of its compressed image, or `null`.
        - `format_sizes` object[], nullable, required: What the compressed file came to in each format, smallest first, when the scan's format was `auto` and more than one format was tried; otherwise `null`.
          - `format` string, required
          - `bytes` integer, required
        - `suggested_alt` string, nullable, required: An AI alt text for an image the page shows without one, written from its compressed copy, or `null`: the image has alt text, the scan was asked for none, it is still being written (the scan's `alt_texts_in_progress` counts it), the day's AI alt texts were used up, or the model gave no usable answer. See [Alt text and file names](/docs/images#alt-text-and-file-names).
    - `share_url` string, uri, nullable, required: The page report's public link while it is shared, or `null`. The link answers only while your plan includes Pro.
    - `created_at` string, date-time, required: When the scan was queued.
    - `updated_at` string, date-time, required: When it last changed.

## Other responses

- `401`: `unauthenticated`: No key was sent, or the key does not exist (it was mistyped or deleted). Send it as `Authorization: Bearer <key>`.
- `403`: `email_not_verified`: The key belongs to an account whose email address is not verified yet. Follow the link in the verification email, then call again with the same key. `account_banned`: The account behind the key has been banned. Its keys stop working with the ban. `scans_not_available`: Your plan does not include page scans.
- `404`: `not_found`: No image or scan with that id on your account, or no such address. An id from another account answers the same way as one that never existed.
- `409`: `scan_not_retryable`: Only a failed or cancelled scan can be retried.
- `429`: `rate_limited`: One of your per-minute limits is spent: requests, compressions or page scans. The compressions and scans are counted together with the website's, so work queued there counts too. Nothing was done; wait for the number of seconds in the `Retry-After` header and send it again. `daily_limit_reached`: Your plan's images, page scans or AI alt texts for the day are used up. `Retry-After` holds the seconds until the rolling 24-hour window opens again. An image sent while only the alt texts are used up still compresses, without one.

---

[API](https://skmtc.dev/iminify/apis/iminify-api.md) · [All operations](https://skmtc.dev/iminify/apis/iminify-api/llms.txt) · [OpenAPI document](https://skmtc.dev/iminify/apis/iminify-api/revisions/12dc614c2c21?raw)
