Skip to content

Errors and media lifecycle

API v1 uses one stable error envelope:

{
"error": {
"code": "unsupported_url",
"message": "Human-readable explanation",
"details": null
}
}

Clients should branch on error.code, not parse message. details may be null or contain structured context. New clients should also tolerate error codes added by future modules.

A malformed URL, unsupported host/path, or URL that does not match an enabled module fails before a scraper result is returned. unsupported_url is a typical routing error code.

A platform can report that a post, track, or account-bound asset no longer exists or cannot be resolved. not_found is the canonical class for content that the module can confidently identify as absent.

Do not treat every upstream parsing failure as not_found: modules can fall back or surface a service/upstream failure when the content’s existence is uncertain.

Machine routes reject missing/invalid X-API-Key values. Browser routes reject missing, invalid, or expired signed web-session bearer tokens. Those mechanisms are intentionally separate.

Platforms can throttle, geo-restrict, require authentication, change response formats, or return temporary service errors. A module may retry or use a documented fallback, but clients should still be prepared for retriable service/rate conditions.

The human message is for diagnostics; application behavior should use the status and error code.

A successful scrape does not make cached media public.

  • Machine /v1/scrape responses can contain protected /media/... paths. Fetch them with the same machine-key boundary.
  • Browser /v1/web/scrape responses use protected /web/media/... paths. Pinchana Web rewrites them to same-origin /api/media/... and its BFF forwards the browser session.

Both media paths support the range behavior required for video/audio playback and resumable requests where the underlying file supports it.

The gateway probes cached image/video files to populate dimensions: {width, height}. A visual asset can legitimately have dimensions: null when the file cannot be inspected. Audio assets have no visual dimensions.

Clients must not infer an error from missing dimensions.

The shared scraper cache is working storage, not permanent object storage. Modules write files into the shared scraper-cache volume and the gateway serves them while present. Cache cleanup can remove old assets according to configured size/lifecycle behavior.

If an integration needs durable storage, copy the authenticated asset into storage you control rather than retaining a Pinchana cache URL indefinitely.

POST /web/convert/gif operates only on an authenticated file already present in the Pinchana cache. It has bounded FFmpeg limits and does not accept arbitrary remote URLs or uploads.

That means a stale/removed cache asset cannot be converted later simply by replaying its old path.

DLP output is separate from the normal scraper cache. Each job gets temporary host storage and an ephemeral worker. Completed files are streamed through the owner-bound DLP route, and job directories expire according to DLP retention settings.

Production defaults use a two-hour job lifetime. DLP storage is intentionally temporary and should not be backed up or synchronized.

For a failed normal scrape:

  1. Confirm the request reached the gateway and authenticated successfully.
  2. Confirm the URL matches an enabled module.
  3. Inspect gateway/module logs without logging secrets or cookies.
  4. Check VPN/Gluetun health if the module depends on current egress.
  5. If scrape succeeds but file access fails, inspect the shared cache and media authentication separately.

For a failed YouTube DLP job, use the DLP operations/preflight path instead of debugging it as a scraper module.