Developer documentation · API v1

Website Image Extraction API

Submit a public webpage, process a list of exact URLs, or discover products in a supported public store. Retrieve image results and verified larger public versions when available, then download the files.

API keys are included with Pro, Business, and Scale. Pro can scan webpages, process URL lists, and preview Store Catalog products. Business and Scale can also process catalog products. API processing shares monthly website credits at 2 credits per successful webpage or catalog product, with no separate API subscription. The website’s free Single Page allowance does not apply to API requests.

What you can do with API v1.3

Process one public webpage

Submit a Single Page job and poll its status until image results are ready.

Process exact URL lists

Submit Multiple URLs runs for the exact public webpages you provide, without catalog discovery.

Discover and process store products

Preview compatible public ecommerce catalogs on Pro or higher. Process selected products with Business or Scale.

Get image metadata and larger versions

Read image URLs, dimensions, labels, formats, and verified public larger versions without AI upscaling.

Download ZIPs and check completeness

Download page, URL-list, or catalog results. Inspect file counts and retry image downloads that failed.

Cancel and retry work

Cancel unfinished jobs or runs, retry failed or unfinished pages, and keep completed results.

API v1.3 covers Single Page, Multiple URLs, and Store Catalog. Pro can preview catalogs through the API without processing credits. Business and Scale can also process selected catalog products. Version 1 uses polling rather than webhooks and does not include official SDKs.

Start your first scan

  1. Sign in, then create a key under Account → API keys. You need Pro or higher.
  2. Save the key securely. It is shown once, does not expire automatically, and can be revoked at any time.
  3. Send it in the Authorization: Bearer header. Keep it on your server, outside browser JavaScript and URLs.

Use https://sourceimagefinder.com/api/v1 on the deployed site. For local testing, use http://127.0.0.1:8787/api/v1. For local testing, plan access comes from your development settings.

Every processing request needs an Idempotency-Key. Generate a new UUID for a new scan and reuse that UUID only when retrying the same request.

curl https://sourceimagefinder.com/api/v1/jobs \
  -H "Authorization: Bearer $SIF_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: your-unique-request-uuid" \
  -d '{"url":"https://example.com/page"}'

A successful submission returns 202 Accepted and a receipt:

{
  "id": "11111111-1111-4111-8111-111111111111",
  "type": "job",
  "links": {"self": "/api/v1/jobs/11111111-1111-4111-8111-111111111111"}
}

Poll the returned path every 2 to 5 seconds. A job moves from queued to processing, then completed, failed, or cancelled. A completed scan may contain zero images. That still counts as successful page processing.

curl "https://sourceimagefinder.com/api/v1/jobs/JOB_ID" \
  -H "Authorization: Bearer $SIF_API_KEY"

curl "https://sourceimagefinder.com/api/v1/jobs/JOB_ID/results?scope=useful&limit=100" \
  -H "Authorization: Bearer $SIF_API_KEY"

curl "https://sourceimagefinder.com/api/v1/jobs/JOB_ID/zip" \
  -H "Authorization: Bearer $SIF_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}' --output images.zip

Only save a response as a ZIP when its HTTP status is 200 and its content type is application/zip. Use the Node.js or PowerShell examples included in the application package for a complete submission, polling, and download flow.

Download filenames: ZIP responses include a Content-Disposition attachment filename, such as allbirds-com-product-images-322b7ecf1234-08af2a4283.zip. Use this header instead of a hardcoded filename. Names distinguish source or workflow, run, export settings/selection, split part, completed-only exports, and failed-file retries. The same export keeps its filename when downloaded again; choose a new local name when preserving multiple copies. The included Node and PowerShell examples read the header and avoid overwriting local ZIP files.

The included PowerShell examples accept -BaseUrl, so you can set the server address directly without relying on the SIF_BASE_URL environment variable in a new terminal. They show the server address in use and include API error details when a request fails.

$env:SIF_API_KEY = Get-Clipboard
.\examples\api-v1.ps1 -Url 'https://example.com/page' -BaseUrl 'http://127.0.0.1:8787'
.\examples\api-v1-bulk.ps1 -Urls 'https://example.com/a','https://example.com/b' -BaseUrl 'http://127.0.0.1:8787'

Endpoints

Method and pathPurposePermission
POST /catalog/previewsCreate a public-store preview (no scan credits).jobs:read
GET /catalog/previews/{id}?page=1Read ten products per page of your retained preview.jobs:read
POST /catalog/jobsProcess explicit product handles from a preview. Business/Scale. Idempotency-Key required.jobs:write
GET /catalog/jobs/{id}Monitor processing, failures and credit-relevant product statuses.jobs:read
POST /catalog/jobs/{id}/retry-failedRetry failed products only, without charging for failures.jobs:write
POST /catalog/jobs/{id}/cancelCancel unfinished products.jobs:write
POST /catalog/jobs/{id}/zipDownload organized completed product images; use part when split.downloads:read
GET /usageShared credit balance, reset date, payment status, and limits.jobs:read
POST /jobsSubmit {"url":"https://example.com/page"}.jobs:write
POST /bulkSubmit {"urls":["https://example.com/a","https://example.com/b"]}. Only those pages are processed.jobs:write
GET /bulk/{id}Read run status and the ordered page list. Each entry includes its job ID and webpage URL.jobs:read
POST /bulk/{id}/cancelSend {} to stop unfinished pages while keeping completed results.jobs:write
POST /bulk/{id}/retry-failedSend {} after the run finishes to retry only failed pages.jobs:write
POST /bulk/{id}/retry-unfinishedSend {} after the run finishes to retry failed or cancelled pages.jobs:write
POST /bulk/{id}/zipDownload completed pages together. Optionally send job_ids, mode, and part.downloads:read
GET /jobs/{id}Read job status, progress, expiry, and result links.jobs:read
GET /jobs/{id}/resultsRead image metadata. Results default to scope=useful; use scope=all to include site UI and review media. Use offset and limit for pagination.jobs:read
POST /jobs/{id}/cancelSend {} to cancel one unfinished page job.jobs:write
POST /jobs/{id}/zipSend {} for useful images, or {"image_ids":["IMAGE_ID"]} for selected images. Returns receipt headers.downloads:read
GET /downloads/{id}Check a ZIP receipt: planned, included, failed, completeness and retry availability.downloads:read
POST /downloads/{id}/retrySend {} to download only failed image files from a previous ZIP.downloads:read

Paths above are relative to /api/v1. All POST bodies must be JSON objects with Content-Type: application/json. Undocumented body fields and query parameters are rejected. Responses are private and should not be cached. Browser sessions cannot authenticate these endpoints.

Resetting your password revokes your API keys. Create new keys afterward to reconnect your scripts.

Keys can access their account’s Single Page and Multiple URLs jobs, including owned jobs started on the website. Pro or higher can create and read owned Store Catalog API previews. Business and Scale can also start and manage owned catalog runs. API keys cannot manage billing or create other keys. Multiple URLs API runs support run-level cancellation, failed/unfinished retry, and combined ZIP downloads. Cancelling a run removes its queued pages first, then stops active pages; queued pages cancelled before processing starts use no credits, while pages that already started can still use their normal 2-credit charge. Version 1 uses polling; it does not include completion webhooks or official SDKs.

Store Catalog API v1.3

Pro, Business, and Scale accounts can preview supported public ecommerce catalogs with an API key. Business and Scale can select exact product handles, start processing, and download product-organized ZIP files. API catalog previews use no processing credits. Processing reserves two credits per selected product and consumes two only for each successful product; failures release their reservation. Existing public store data discovery and platform restrictions apply. Business allows 250 selected products per run; Scale allows 1,000.

The API uses the same public Store Catalog discovery paths as the website, with tested patterns for Shopify, WooCommerce, Wix Stores, PrestaShop, BigCommerce, Magento / Adobe Commerce, Shopware 6, and OpenCart. Platform support varies by public URL, theme, and available store data; a successful preview is not guaranteed on every storefront. Squarespace product-page image scanning is available, but Store Catalog discovery is conditional, not a dedicated Squarespace adapter. See supported ecommerce platforms and URL types before processing a catalog.

POST /api/v1/catalog/previews
Authorization: Bearer YOUR_API_KEY
Content-Type: application/json
{"url":"https://example.com/collections/all"}

GET /api/v1/catalog/previews/PREVIEW_ID?page=1
Authorization: Bearer YOUR_API_KEY

POST /api/v1/catalog/jobs
Authorization: Bearer YOUR_API_KEY
Content-Type: application/json
Idempotency-Key: NEW_UNIQUE_KEY
{"preview_id":"PREVIEW_ID","product_handles":["product-handle-1"]}

GET /api/v1/catalog/jobs/RUN_ID
Authorization: Bearer YOUR_API_KEY

POST /api/v1/catalog/jobs/RUN_ID/zip
Authorization: Bearer YOUR_API_KEY
Content-Type: application/json
{"mode":"focused"}

Previews are owner-bound, retain their selected products for up to 24 hours, and return 10 products per page. Only product handles present in the same account's preview can be submitted, and the store is rediscovered before work starts. Failed product retries use POST /catalog/jobs/{id}/retry-failed with {}; cancelled runs cannot use failed-only retry. The ZIP includes completed products after all members finish. Inspect X-SIF-Download-ID to check completeness and retry any failed image-file downloads at no additional scan-credit cost. ZIP receipt state lives for up to 30 minutes in memory, whereas catalog scan results remain accessible for 24 hours.

Examples: examples/api-v13-catalog.mjs and examples/api-v13-catalog.ps1.

ZIP completeness and retry (API v1.2)

POST /jobs/{id}/zip and POST /bulk/{id}/zip return an X-SIF-Download-ID header with the ZIP stream. The matching X-SIF-Download-Status header is a relative link to GET /api/v1/downloads/{id}. Use the same Bearer API key with downloads:read permission.

GET /api/v1/downloads/DOWNLOAD_ID
Authorization: Bearer YOUR_API_KEY

{ "download": { "state": "ready", "totalFiles": 25, "includedFiles": 23, "failedFiles": 2,
  "complete": false, "retryAvailable": true, "failures": [ ... ], "expiresAt": "..." } }

If retryAvailable is true, call POST /api/v1/downloads/DOWNLOAD_ID/retry with {} and save the returned ZIP separately. It contains only images that failed in the prior attempt. Query the same receipt again for updated counts. ZIP retries cost no additional scan credits and do not rescan webpages. For Single Page product images, an explicit failed-file retry may include a separately named previously verified alternative if the exact selected file still cannot be downloaded. In that case the additive alternativeFiles receipt count reports fulfilled selections delivered as alternatives, and the retry ZIP contains verified-alternatives.csv; the original requested file is not silently replaced. They count against the ZIP-build rate limit.

Receipts are held in server memory for up to 30 minutes after their latest update and are lost on server restart. Jobs must also remain within the 24-hour result retention window. A status check may return 404 when a receipt is gone; recreate the original ZIP to get a fresh receipt. A completed ZIP download does not guarantee complete: true, so check the receipt when file completeness matters.

Read image results

GET /jobs/{id} returns a job object. GET /jobs/{id}/results returns the page title, requested and final URLs, scan time, expiry, the active result scope, an images array, and a pagination object. The default scope=useful excludes site-ui and review-media so the JSON result matches the normal downloadable image set more closely. Use scope=all when you need every detected asset. Pagination counts and next_offset apply to the selected scope. The default page size is 100 images; the maximum is 500.

GET /api/v1/jobs/JOB_ID/results?scope=useful&limit=100
GET /api/v1/jobs/JOB_ID/results?scope=all&limit=100
{
  "id": "image-family-id",
  "category": "product-gallery",
  "label": "SOURCE RECOVERED",
  "alt_text": "Example product",
  "product_linked": true,
  "variant_ids": [],
  "page_max": {"url":"https://example.com/small.jpg", "width":400, "height":400, "format":"jpeg", "bytes":18000},
  "best": {"url":"https://example.com/large.jpg", "width":1400, "height":1400, "format":"jpeg", "bytes":170000, "verdict":"source-recovered"},
  "pixel_gain": 12.25,
  "page_versions": []
}

PAGE MAX is the best version verified from the image links on the page. SOURCE RECOVERED means a better public version was found and verified. BEST AVAILABLE reports the best verified file found without claiming a recovered original. POSSIBLE BETTER VERSION is not proof of a verified improvement. Inspect best.verdict instead of assuming every result is a recovered original. No AI upscaling is performed.

Source URLs belong to the source website and may later change or stop working. Download files before the result expires. ZIPs keep the source file formats. They exclude review/customer-upload media; the default also excludes site UI. Explicit image IDs can include site UI. ZIPs can include a failure report when a source file is no longer available. For Multiple URLs, POST /bulk/{id}/zip can combine completed pages. Use job_ids to select pages and mode as focused or all-useful. If an export must be split, the API returns download_split_required with the number of parts; repeat the request with part set to 1 through that number.

Credits, plans, and limits

PlanMonthly priceMonthly creditsURLs per runCatalog products per runActive Single Page jobs
Pro$91,00025Preview only2
Business$294,0002502504
Scale$9916,0001,0001,0008

All prices are USD per month. API access is included in each listed paid plan, without a separate API fee. These are the default plan limits; GET /usage returns the account’s configured webpage limits. There is one active Multiple URLs run per account across API and website. Active Single Page limits also count that account’s website jobs. Jobs share the website’s processing queue, so submission limits do not guarantee simultaneous execution.

  • 2 credits per successfully processed unique webpage or Store Catalog product. Duplicate URLs within one webpage request are normalized and processed once. Separate requests are separate scans. Catalog processing requires Business or Scale; its preview uses no credits.
  • Credits are reserved before work starts. Bulk reservations settle after all jobs in the operation finish. Failed processing and queued cancellations release credits; cancellation after processing starts can use 2 credits.
  • Store Catalog previews, status polling, results, and downloads cost no credits. There are no automatic overage charges. Credits reset monthly and do not roll over.
  • Default request limits: 120 requests per minute per account, 30 new starts per 5 minutes, and 60 ZIP builds per 10 minutes. Starts and downloads share the website limits. There is also a 300-request-per-minute network limit and a 30-failed-authentication-per-minute network limit. Rotating keys does not reset account limits.
  • Responses report X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset for the last applicable limit. Reset is Unix time in seconds. On HTTP 429, follow Retry-After.
  • Results are available for up to 24 hours after that page job finishes, or less if the deployment’s retention is shorter. Check each job’s expires_at for its expiry time. Download early pages in a long bulk run promptly. HTTP 410 means expired; after cleanup the same ID may return 404.
  • New processing stops when credits run out, payment requires attention, or the paid plan ends. Existing keys can still read and download retained results. You can revoke keys after downgrading.
  • When billing_refresh_required is true, the displayed usage belongs to the previous billing period. The server verifies the current subscription before accepting new paid work.

Errors and safe retries

{"error":{"code":"insufficient_credits","message":"This run needs 2 credits, but only 0 remain in this credit period","request_id":"request-uuid"}}
HTTPCommon codesWhat to do
400 / 415invalid_request, invalid_url, invalid_json, invalid_pagination, idempotency_key_required, invalid_idempotency_key, unsupported_media_type, plan_limit_exceededFix the request or reduce its size.
401 / 403invalid_api_key, insufficient_scope, plan_requiredCheck the key, permissions, and your plan.
402insufficient_credits, payment_requiredCheck credits or billing.
404 / 410not_found, download_not_found, result_expiredCheck the ID and account, or start a new scan.
405method_not_allowedUse the method in the Allow header.
409job_not_ready, no_failed_files, download_building, retry_limit_exceeded, run_active, retry_unfinished_required, nothing_to_retry, download_split_required, concurrency_limit, idempotency_conflict, request_incomplete, idempotency_capacity, conflictWait for active work, choose the correct retry action or ZIP part, or correct a conflicting retry.
400 / 413download_unavailable, download_too_large, request_too_largeSelect fewer images or send a smaller request.
422 / 502 / 504unprocessable_source, upstream_error, timeoutCheck that the public source is supported, or retry after a temporary upstream failure.
429 / 503 / 500rate_limit_exceeded, service_unavailable, internal_errorBack off. Retry processing with the same Idempotency-Key.

Successful processing receipts can be replayed for 24 hours from submission, even across a server restart or a rotated key belonging to the same account. Idempotency-Replayed: true identifies a replay. Reusing a key for another request returns 409. A retry after 24 hours may create a new paid scan. A verified failure before jobs or credits were created can be retried after the problem is fixed.

If a server interruption leaves an uncertain submission, the server preserves its retry record and returns request_incomplete until it can recover the original job IDs. Do not switch to a new key to get around this error; check usage and contact support with request_id. A successful receipt confirms submission, not completed extraction.

Version 1 may add response fields. Clients should ignore unknown response fields. Breaking changes use a new versioned path. Use the OpenAPI document as the machine-readable contract.