# ASO-Direct Image URL Preflight (`gwave-aso/aso-direct-image-preflight`) Actor

Inspect public image URLs before imports. Check HTTP status, fully decode supported static images, and report dimensions, size and exact duplicates in JSON/CSV. Pay $0.001 per qualifying result. Does not convert images or guarantee importer acceptance.

- **URL**: https://apify.com/gwave-aso/aso-direct-image-preflight.md
- **Developed by:** [ASO-Direct](https://apify.com/gwave-aso) (community)
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$1.00 / 1,000 image inspection results

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## ASO-Direct Image URL Preflight

Inspect public product-image URLs before an import or ingestion job. Version 0.1.5 checks HTTP responses and fully decodes supported static images, then returns ordered JSON/CSV records with status, format, dimensions, size and duplicate references.

A passing result does not guarantee acceptance by Shopify, ZenPlus or any other importer, image rights, image-content safety, or future URL availability. This Actor does not convert, resize, upload or import images.

### Input

Supply an array of public, unauthenticated HTTP/HTTPS URLs in `urls`. Never supply signed private links, credentials or tokens. Apify retains the full input according to storage settings even though result URLs are redacted.

```json
{
  "urls": ["https://www.w3.org/Icons/w3c_home.png"],
  "max_items": 1,
  "concurrency": 1,
  "timeout": 5,
  "max_bytes": 65536,
  "max_pixels": 100000,
  "max_redirects": 2
}
```

This is a public third-party example; future availability and results may change.

- `max_items`: default 100, maximum 1,000. Input count must not exceed this value.
- `concurrency`: default 2, maximum 4. Applies to the local CLI/API; the billed Actor processes rows sequentially.
- `timeout`: default 15, maximum 30 seconds, separately for fetch and decoding.
- `max_bytes`: default 10 MiB, maximum 20 MiB per response.
- `max_pixels`: default 10 million, maximum 20 million.
- `max_redirects`: default 5, maximum 8.

Limits must be positive integers. Cookies, credentials, custom headers and custom proxies are unsupported. These limits are safety bounds, not maximum-throughput or host-memory guarantees.

### Results

Only static PNG, JPEG, WebP and GIF that pass identification, verification and full decoding succeed. Animated/multiframe images and other formats are rejected. Filename and Content-Type do not establish success.

Each completed input produces a default Dataset row and a `RESULT_######` key-value record. Cumulative JSON in `OUTPUT` and CSV in `RESULTS_CSV` are written only when the Actor finishes normally, including a spending-limit stop. An aborted or crashed run can have saved, charged Dataset/individual records but no cumulative JSON or CSV. `RUN_SUMMARY` reports completed and unprocessed counts, the next input index, stop reason and confirmed custom charges. Missing metadata on failed rows means unknown, not zero.

`sha256`/`duplicate_of` identify identical encoded files; `pixel_sha256`/`pixel_duplicate_of` identify identical width, height and decoded RGBA pixels. References point to the first matching successful index. This is not perceptual matching or EXIF/ICC normalization.

### Pricing and spending limits

Price: **$0.001 per qualifying inspection result ($1 per 1,000)**, using only the `image-inspection-result` custom event. No startup fee or automatic per-Dataset-row fee is configured.

A charge is eligible only after a retrievable result is saved, once per exact input URL string per run:

- A fully decoded supported static image.
- An observed HTTP 404 or 410.
- A complete, nonempty HTTP 2xx response conclusively classified as invalid image, unsupported format or unsupported animated image.

Exact repeated URL strings reuse their first result without another fetch or charge. Different URL strings may each be charged even if their image bytes or decoded pixels match. Query order, escapes and fragments are part of exact URL identity.

Preflight URL rejection, HTTP 401/403/429/5xx, DNS/TLS/protocol failures, timeouts, decoding/process failures, size/pixel limits and incomplete responses are not chargeable under this contract.

Use Apify's **Maximum cost per run** setting, not an input property named `max_charged_items`. When the event budget is exhausted the Actor stops; trailing inputs are not inspected and do not receive completed rows. The event-charge cap is not a general compute/storage spending cap.

Result storage and charging are separate operations. Exactly-once billing is not promised. Resurrecting the same run with identical input can repair final exports from completed journal entries without repeating completed inspections or charges. Starting a new run is separate work and may charge again. If interrupted with an unresolved delivery or charge intent, the Actor stops for reconciliation rather than blindly repeating operations. Do not clear billing state or retry a charge without checking the original platform ledger and saved records.

### Security and privacy

Only public addresses are accepted. URL and redirect checks, DNS/IP pinning, TLS hostname verification, bounded requests and subprocess decoding reduce risk. They are not an independent security certification. Results redact URL paths, query strings and fragments; hostnames remain. Full INPUT may still contain the submitted URLs in Apify storage. Manage retention and inspect results before sharing.

### Verified scope

Version 0.1.5 was tested on Apify with the Python SDK 4.1.0. Tests covered a spending limit below one event, a one-event limit, a supported PNG, exact URL repetition, a rejected FTP URL, and a distinct URL pointing to identical image content. Dataset, cumulative JSON, journal rows and CSV agreed in the mixed case. These tests do not certify maximum-load operation, every format variant, broad network environments or downstream importer acceptance.

### Troubleshooting

For HTTP failures, verify the object exists and allows unauthenticated access. For unsupported/animated/invalid files, prepare a supported static image outside this Actor. For size/time limits, split work or adjust only within the documented bounds. Private/metadata address restrictions cannot be bypassed. An Actor run can succeed while individual rows report expected failures; inspect each row and `RUN_SUMMARY`.

No custom integration setup, support SLA or guaranteed savings is included. For issue reports, include the version, reason code and a nonsensitive reproduction; remove secret URLs and private input first.

# Changelog

This Actor's version history is a separate document: https://apify.com/gwave-aso/aso-direct-image-preflight/changelog.md

# Actor input Schema

## `urls` (type: `array`):

Public unauthenticated URLs only; no credentials or tokens. Output paths and queries are redacted.

## `max_items` (type: `integer`):

Positive integer; see README for units and safety caps.

## `concurrency` (type: `integer`):

Positive integer; see README for units and safety caps.

## `timeout` (type: `integer`):

Positive integer; see README for units and safety caps.

## `max_bytes` (type: `integer`):

Positive integer; see README for units and safety caps.

## `max_pixels` (type: `integer`):

Positive integer; see README for units and safety caps.

## `max_redirects` (type: `integer`):

Positive integer; see README for units and safety caps.

## Actor input object example

```json
{
  "urls": [
    "https://www.w3.org/Icons/w3c_home.png"
  ],
  "max_items": 100,
  "concurrency": 2,
  "timeout": 15,
  "max_bytes": 10485760,
  "max_pixels": 10000000,
  "max_redirects": 5
}
```

# Actor output Schema

## `results` (type: `string`):

One object per completed input URL, including completed refusals; a spending-limit stop can leave trailing URLs unprocessed. Check runSummary.

## `jsonReport` (type: `string`):

KV key OUTPUT: ordered array of completed results; empty when stopped before any inspection. Check runSummary for unprocessed inputs.

## `csvReport` (type: `string`):

KV key RESULTS_CSV: text/csv report written by the adapter; not product-import data.

## `runSummary` (type: `string`):

KV key RUN_SUMMARY: completed/input/unprocessed row counts, next unprocessed zero-based input index, stop reason and confirmed charge count.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "urls": [
        "https://www.w3.org/Icons/w3c_home.png"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("gwave-aso/aso-direct-image-preflight").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = { "urls": ["https://www.w3.org/Icons/w3c_home.png"] }

# Run the Actor and wait for it to finish
run = client.actor("gwave-aso/aso-direct-image-preflight").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "urls": [
    "https://www.w3.org/Icons/w3c_home.png"
  ]
}' |
apify call gwave-aso/aso-direct-image-preflight --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,gwave-aso/aso-direct-image-preflight"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/VCG004BNMZVU0AdYQ/builds/28acHZYDSMdRlGQ1v/openapi.json
