> ## Documentation Index
> Fetch the complete documentation index at: https://docs.prefetch.io/llms.txt
> Use this file to discover all available pages before exploring further.

# DELETE /crawl/{id}

> Stop a running crawl. Pages already fetched stay readable. Free.

## Overview

Stops a crawl that is `pending` or `running`. The worker notices within a few pages and stops fetching.

Nothing is thrown away: pages already crawled stay readable through [`GET /crawl/{id}`](/api-reference/endpoint/crawl-status) until the crawl expires, 24 hours after it stopped. They are billed on the next status call as usual, so you pay for what was fetched and nothing more.

Cancelling is free.

## Example request

<CodeGroup>
  ```bash cURL theme={null}
  curl -X DELETE "https://api.prefetch.io/crawl/crw_9f2c1a7b4e0d4c3a8b1e5f7d2c9a0b3e" \
    -H "X-API-Key: $PREFETCH_API_KEY"
  ```

  ```javascript Node.js theme={null}
  const res = await fetch(
    `https://api.prefetch.io/crawl/${crawlId}`,
    { method: "DELETE", headers: { "X-API-Key": process.env.PREFETCH_API_KEY } }
  );
  const { data } = await res.json();
  console.log(data.status); // "cancelled"
  ```

  ```python Python theme={null}
  import requests, os

  r = requests.delete(
      f"https://api.prefetch.io/crawl/{crawl_id}",
      headers={"X-API-Key": os.environ["PREFETCH_API_KEY"]},
  )
  print(r.json()["data"]["status"])  # "cancelled"
  ```
</CodeGroup>

## Example response

```json theme={null}
{
  "success": true,
  "data": {
    "id": "crw_9f2c1a7b4e0d4c3a8b1e5f7d2c9a0b3e",
    "status": "cancelled",
    "url": "https://docs.stripe.com",
    "total": 38,
    "completed": 12,
    "failed": 1,
    "credits_used": 36,
    "created_at": "2026-08-20T09:14:03.221Z",
    "started_at": "2026-08-20T09:14:04.010Z",
    "finished_at": "2026-08-20T09:16:41.882Z",
    "expires_at": "2026-08-21T09:14:03.221Z",
    "error": null
  },
  "meta": {
    "requestId": "e7b6a5f4-bd0e-4f70-c15c-4d6e8f0a2b43",
    "durationMs": 61
  }
}
```

## Behavior

* **Already finished?** Cancelling a `completed`, `failed`, or `cancelled` crawl is a no-op. You get `200` with the crawl's real final state rather than an error.
* **Not yet started?** The queued job is removed, so no pages are ever fetched.
* **Unknown or expired id?** `404`.

A crawl you do not own also returns `404` rather than `403`. Crawl ids are unguessable, and confirming that some id exists is the only thing an enumeration attempt is after.

## Related

<CardGroup cols={2}>
  <Card title="POST /crawl" icon="spider" href="/api-reference/endpoint/crawl">
    Start a crawl.
  </Card>

  <Card title="GET /crawl/{id}" icon="list-check" href="/api-reference/endpoint/crawl-status">
    Read progress and results.
  </Card>
</CardGroup>


## OpenAPI

````yaml DELETE /crawl/{id}
openapi: 3.1.0
info:
  title: Prefetch API
  description: >-
    Extract brand identity, company data, screenshots, IAB classifications, and
    clean page content from any URL.
  version: 1.0.0
  contact:
    email: support@prefetch.io
servers:
  - url: https://api.prefetch.io
    description: Production
security:
  - apiKey: []
tags:
  - name: Endpoints
    description: Data extraction endpoints. All require authentication and consume credits.
  - name: Health
    description: Health and readiness probes. No authentication required.
paths:
  /crawl/{id}:
    delete:
      tags:
        - Endpoints
      summary: Cancel a crawl
      description: >-
        Stops a running crawl. Pages already crawled stay readable until the
        crawl expires, and are billed on the next status call as usual.
        Cancelling a finished crawl is a no-op that returns its final state.
        Free.
      operationId: cancelCrawl
      parameters:
        - $ref: '#/components/parameters/crawlId'
      responses:
        '200':
          description: Crawl cancelled, or already finished.
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    enum:
                      - true
                  data:
                    $ref: '#/components/schemas/CrawlStatusData'
                  meta:
                    $ref: '#/components/schemas/Meta'
                required:
                  - success
                  - data
                  - meta
        '400':
          description: Invalid or missing parameters.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Missing API key.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: Revoked key, expired key, credit limit, or blocklisted URL.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Crawl not found, expired, or owned by another key.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '422':
          description: The URL hostname could not be resolved.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '429':
          description: Rate limit exceeded.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '503':
          description: Service temporarily busy. Retry shortly.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '504':
          description: Request timed out.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
components:
  parameters:
    crawlId:
      name: id
      in: path
      required: true
      description: The crawl id returned by `POST /crawl`.
      schema:
        type: string
        example: crw_9f2c1a7b4e0d4c3a8b1e5f7d2c9a0b3e
  schemas:
    CrawlStatusData:
      type: object
      properties:
        id:
          type: string
        status:
          type: string
          enum:
            - pending
            - running
            - completed
            - failed
            - cancelled
        url:
          type: string
        total:
          type: integer
          description: >-
            Pages the crawl expects to fetch, as currently known. Rises as it
            discovers more.
        completed:
          type: integer
        failed:
          type: integer
        credits_used:
          type: integer
        created_at:
          type: string
          format: date-time
        started_at:
          type: string
          format: date-time
          nullable: true
        finished_at:
          type: string
          format: date-time
          nullable: true
        expires_at:
          type: string
          format: date-time
        error:
          type: string
          nullable: true
        next:
          type: string
          nullable: true
          description: URL for the next page of results, or null when there are no more.
        data:
          type: array
          items:
            $ref: '#/components/schemas/CrawlPage'
          description: Crawled pages, in completion order.
    Meta:
      type: object
      properties:
        requestId:
          type: string
          format: uuid
          description: Unique identifier for this request.
          example: a3f2c1d4-7b6e-4f2a-9c1d-8e3f2a1b4c5d
        durationMs:
          type: integer
          nullable: true
          description: Time taken to process the request in milliseconds.
          example: 1842
      required:
        - requestId
        - durationMs
    ErrorResponse:
      type: object
      properties:
        success:
          type: boolean
          enum:
            - false
        error:
          type: string
          description: Human-readable error message.
          example: Credit limit exceeded
        meta:
          $ref: '#/components/schemas/Meta'
      required:
        - success
        - error
        - meta
    CrawlPage:
      type: object
      description: >-
        One crawled page. Carries the same fields `GET /scrape` returns, plus
        the crawl's own bookkeeping.
      allOf:
        - type: object
          properties:
            url:
              type: string
            depth:
              type: integer
              description: >-
                How many links from the start URL. Sitemap-seeded pages are
                depth 0.
            status_code:
              type: integer
              nullable: true
            ok:
              type: boolean
              description: >-
                False when the page could not be fetched. You are not charged
                for it.
            error:
              type: string
              nullable: true
        - $ref: '#/components/schemas/ScrapePayload'
    ScrapePayload:
      type: object
      properties:
        url:
          type: string
        final_url:
          type: string
        domain:
          type: string
          nullable: true
          example: stripe.com
        status_code:
          type: integer
          nullable: true
        metadata:
          $ref: '#/components/schemas/ScrapeMetadata'
        markdown:
          $ref: '#/components/schemas/MarkdownBlock'
        summary:
          $ref: '#/components/schemas/SummaryBlock'
        html:
          $ref: '#/components/schemas/HtmlBlock'
        raw_html:
          $ref: '#/components/schemas/HtmlBlock'
        links:
          $ref: '#/components/schemas/LinksBlock'
        images:
          $ref: '#/components/schemas/ScrapeImagesBlock'
        json:
          $ref: '#/components/schemas/JsonBlock'
        warnings:
          type: array
          items:
            type: string
          description: Non-fatal problems, such as a format that could not be produced.
      description: >-
        The page content fields. Which of them are present depends on the
        `formats` requested.
    ScrapeMetadata:
      type: object
      description: Always present, whatever formats were requested.
      properties:
        source_url:
          type: string
          nullable: true
          description: The URL you requested.
        final_url:
          type: string
          nullable: true
          description: The URL after redirects.
        status_code:
          type: integer
          nullable: true
        title:
          type: string
          nullable: true
          example: Stripe | Financial Infrastructure
        description:
          type: string
          nullable: true
        language:
          type: string
          nullable: true
          example: en
        canonical_url:
          type: string
          nullable: true
        favicon:
          type: string
          nullable: true
        author:
          type: string
          nullable: true
        site_name:
          type: string
          nullable: true
        published_time:
          type: string
          nullable: true
        modified_time:
          type: string
          nullable: true
        robots:
          type: string
          nullable: true
          description: The page's own robots meta tag.
        keywords:
          type: array
          items:
            type: string
        open_graph:
          type: object
          additionalProperties:
            type: string
        twitter:
          type: object
          additionalProperties:
            type: string
        json_ld:
          type: array
          items:
            type: object
          description: Parsed JSON-LD blocks, up to 10.
        headings:
          type: array
          description: The page's heading outline, up to 100 entries.
          items:
            type: object
            properties:
              level:
                type: integer
              text:
                type: string
    MarkdownBlock:
      type: object
      properties:
        content:
          type: string
          description: >-
            GitHub Flavored Markdown. Links and images are resolved to absolute
            URLs.
        char_count:
          type: integer
        word_count:
          type: integer
        truncated:
          type: boolean
          description: True when the content hit the 1 MB size cap and was cut.
        main_content_only:
          type: boolean
          description: >-
            True when boilerplate was successfully isolated away. False means
            the full page body was returned.
    SummaryBlock:
      type: object
      properties:
        text:
          type: string
          nullable: true
          description: Null when the summary could not be produced; see `warnings`.
        model:
          type: string
          nullable: true
    HtmlBlock:
      type: object
      properties:
        content:
          type: string
        char_count:
          type: integer
        truncated:
          type: boolean
        main_content_only:
          type: boolean
    LinksBlock:
      type: object
      properties:
        internal:
          type: array
          description: Links on the same site, subdomains included.
          items:
            $ref: '#/components/schemas/ScrapeLinkItem'
        external:
          type: array
          items:
            $ref: '#/components/schemas/ScrapeLinkItem'
        count:
          type: integer
    ScrapeImagesBlock:
      type: object
      properties:
        assets:
          type: array
          items:
            $ref: '#/components/schemas/ScrapeImageItem'
        og_image:
          type: string
          nullable: true
        twitter_image:
          type: string
          nullable: true
        count:
          type: integer
    JsonBlock:
      type: object
      properties:
        data:
          type: object
          nullable: true
          description: The extracted object, shaped by your prompt or schema.
        model:
          type: string
          nullable: true
    ScrapeLinkItem:
      type: object
      properties:
        url:
          type: string
        text:
          type: string
          nullable: true
          description: The anchor text.
        title:
          type: string
          nullable: true
        rel:
          type: string
          nullable: true
    ScrapeImageItem:
      type: object
      properties:
        url:
          type: string
        alt:
          type: string
          nullable: true
        width:
          type: integer
          nullable: true
        height:
          type: integer
          nullable: true
        loading:
          type: string
          nullable: true
  securitySchemes:
    apiKey:
      type: apiKey
      in: header
      name: X-API-Key
      description: Your Prefetch API key. Obtain one from the dashboard.

````