NAV
cURL Python PHP

Introduction

The PiXhost API v2 can upload images and covers, create galleries, and check the current availability of image pages.

Supported image formats:

The maximum file size is 10 MB per uploaded image.

For questions or issues, contact pixhost.to@gmail.com.

API Domains

The API is available on all PiXhost domains:

Use the API hostname matching the PiXhost domain whose links you want in the response. The examples below use api.pixhost.cc.

Conventions

Requests use UTF-8 encoding. Send Accept: application/json.

Image and cover uploads use multipart/form-data. Do not set its Content-Type header manually when using cURL, Python Requests, or PHP cURL; the client must add the multipart boundary.

Gallery requests use application/x-www-form-urlencoded.

Successful upload and gallery creation responses use application/json; charset=UTF-8. API v2 does not require an API key.

Management URLs are opt-in so existing response bodies remain unchanged. Send include_manage_url=1 when uploading a standalone image or creating a gallery to receive a manage_url field in that creation response. Keep that URL private: it authorizes rename and delete operations and cannot be recovered later.

Changelog

Images

Upload Image

Uploads one image.

HTTP Request

POST https://api.pixhost.cc/images

curl --include "https://api.pixhost.cc/images" \
  -H 'Accept: application/json' \
  -F 'img=@image.jpg' \
  -F 'content_type=0' \
  -F 'max_th_size=420'
from pathlib import Path

import requests

with Path("image.jpg").open("rb") as image:
    response = requests.post(
        "https://api.pixhost.cc/images",
        files={"img": ("image.jpg", image, "image/jpeg")},
        data={
            "content_type": "0",
            "max_th_size": "420",
        },
        headers={"Accept": "application/json"},
        timeout=120,
    )

response.raise_for_status()
print(response.json())
<?php
$curl = curl_init('https://api.pixhost.cc/images');
curl_setopt_array($curl, [
    CURLOPT_POST => true,
    CURLOPT_POSTFIELDS => [
        'img' => new CURLFile(__DIR__ . '/image.jpg', 'image/jpeg', 'image.jpg'),
        'content_type' => '0',
        'max_th_size' => '420',
    ],
    CURLOPT_HTTPHEADER => ['Accept: application/json'],
    CURLOPT_RETURNTRANSFER => true,
]);

$response = curl_exec($curl);
$status = curl_getinfo($curl, CURLINFO_HTTP_CODE);
curl_close($curl);

echo $response;

Response headers

HTTP/1.1 200 OK
Content-Type: application/json; charset=UTF-8

Response body

{
  "name": "image.jpg",
  "show_url": "https://pixhost.cc/show/8582/563_image.jpg",
  "th_url": "https://t1.pixhost.cc/thumbs/8582/563_image.jpg"
}

Form Parameters

Parameter Type Required Values Description
img file yes JPEG, PNG, GIF, WebP, AVIF Image to upload
content_type integer yes 0, 1 0 for safe-for-work content, 1 for NSFW content
max_th_size integer no 150-500 Maximum thumbnail width or height; default is 200
gallery_hash string no Gallery identifier; supply together with gallery_upload_hash
gallery_upload_hash string no Gallery upload token; supply together with gallery_hash
include_manage_url integer no 0, 1 Set to 1 to add a management URL for a standalone image; ignored for images uploaded into a gallery

Response Fields

Field Type Description
name string Original image filename without the generated numeric prefix
show_url string Public image page URL
th_url string Direct thumbnail URL
manage_url string Optional private edit/delete URL; returned only when include_manage_url=1

Check Image Status

Checks whether public PiXhost image pages are currently available according to the application database. This does not fetch image files or CDN nodes, so a stale CDN copy can temporarily remain accessible after the API reports deleted.

Only exact public show URLs on pixhost.to, pixhost.cc, or pixho.st and their www aliases are accepted. Historical http links are accepted in addition to https. Direct image URLs, thumbnail URLs, URLs containing credentials, ports, query strings, or fragments, and URLs on other hosts receive the per-item invalid status.

HTTP Request

POST https://api.pixhost.cc/images/status

curl --include "https://api.pixhost.cc/images/status" \
  -H 'Accept: application/json' \
  -H 'Content-Type: application/json' \
  --data '{"urls":["https://pixhost.cc/show/8582/563_image.jpg","https://example.com/image.jpg"]}'
import requests

response = requests.post(
    "https://api.pixhost.cc/images/status",
    json={
        "urls": [
            "https://pixhost.cc/show/8582/563_image.jpg",
            "https://example.com/image.jpg",
        ]
    },
    headers={"Accept": "application/json"},
    timeout=30,
)

response.raise_for_status()
print(response.json())
<?php
$curl = curl_init('https://api.pixhost.cc/images/status');
$body = json_encode([
    'urls' => [
        'https://pixhost.cc/show/8582/563_image.jpg',
        'https://example.com/image.jpg',
    ],
]);

curl_setopt_array($curl, [
    CURLOPT_POST => true,
    CURLOPT_POSTFIELDS => $body,
    CURLOPT_HTTPHEADER => [
        'Accept: application/json',
        'Content-Type: application/json',
    ],
    CURLOPT_RETURNTRANSFER => true,
]);

$response = curl_exec($curl);
$status = curl_getinfo($curl, CURLINFO_HTTP_CODE);
curl_close($curl);

echo $response;

Response body

{
  "results": [
    {
      "url": "https://pixhost.cc/show/8582/563_image.jpg",
      "status": "available"
    },
    {
      "url": "https://example.com/image.jpg",
      "status": "invalid"
    }
  ]
}

Results preserve the input order and duplicates. A syntactically valid batch returns 200 OK; malformed or foreign URL strings are reported individually as invalid instead of failing the whole batch.

JSON Parameters

ParameterTypeRequiredDescription
urlsarray of stringsyesBetween 1 and 100 image show URLs; each URL may contain at most 512 bytes

The JSON request body is limited to 64 KiB. The endpoint allows a sustained rate of 10 requests per minute per client IP with a burst allowance of 5 requests. A rate-limited request returns 429 Too Many Requests with a Retry-After header. Responses use Cache-Control: no-store.

Result Statuses

StatusMeaning
availableThe exact image URL exists, is not deleted, and is not part of an unfinished or deleted gallery
deletedThe exact image URL or its gallery has been marked as deleted
not_foundNo database record matches the complete directory and filename, or its gallery record is missing
pendingThe image belongs to a gallery that has not yet been finalized
invalidThe value is not an accepted PiXhost public image show URL

Upload Cover

Uploads a cover composed of a required left image and an optional right image.

HTTP Request

POST https://api.pixhost.cc/covers

curl --include "https://api.pixhost.cc/covers" \
  -H 'Accept: application/json' \
  -F 'img_left=@left.jpg' \
  -F 'img_right=@right.png' \
  -F 'content_type=0'
from pathlib import Path

import requests

with Path("left.jpg").open("rb") as left, Path("right.png").open("rb") as right:
    response = requests.post(
        "https://api.pixhost.cc/covers",
        files={
            "img_left": ("left.jpg", left, "image/jpeg"),
            "img_right": ("right.png", right, "image/png"),
        },
        data={"content_type": "0"},
        headers={"Accept": "application/json"},
        timeout=120,
    )

response.raise_for_status()
print(response.json())
<?php
$curl = curl_init('https://api.pixhost.cc/covers');
curl_setopt_array($curl, [
    CURLOPT_POST => true,
    CURLOPT_POSTFIELDS => [
        'img_left' => new CURLFile(__DIR__ . '/left.jpg', 'image/jpeg', 'left.jpg'),
        'img_right' => new CURLFile(__DIR__ . '/right.png', 'image/png', 'right.png'),
        'content_type' => '0',
    ],
    CURLOPT_HTTPHEADER => ['Accept: application/json'],
    CURLOPT_RETURNTRANSFER => true,
]);

$response = curl_exec($curl);
$status = curl_getinfo($curl, CURLINFO_HTTP_CODE);
curl_close($curl);

echo $response;

Response headers

HTTP/1.1 200 OK
Content-Type: application/json; charset=UTF-8

Response body

{
  "name": "left.jpg",
  "show_url": "https://pixhost.cc/show/8582/568_left.jpg",
  "th_url": "https://t1.pixhost.cc/thumbs/8582/568_left.jpg"
}

Form Parameters

Parameter Type Required Values Description
img_left file yes JPEG, PNG, GIF, WebP, AVIF Left cover image
img_right file no JPEG, PNG, GIF, WebP, AVIF Right cover image
content_type integer yes 0, 1 0 for safe-for-work content, 1 for NSFW content
gallery_hash string no Gallery identifier; supply together with gallery_upload_hash
gallery_upload_hash string no Gallery upload token; supply together with gallery_hash
include_manage_url integer no 0, 1 Set to 1 to add a management URL for a standalone cover; ignored for covers uploaded into a gallery

Response Fields

Field Type Description
name string Left image filename without the generated numeric prefix
show_url string Public cover page URL
th_url string Direct thumbnail URL
manage_url string Optional private edit/delete URL; returned only when include_manage_url=1

Galleries

Gallery creation is a three-step process:

  1. Create a gallery and retain both returned hashes.
  2. Upload images or covers with gallery_hash and gallery_upload_hash.
  3. Finalize the gallery.

HTTP Request

POST https://api.pixhost.cc/galleries

curl --include "https://api.pixhost.cc/galleries" \
  -H 'Accept: application/json' \
  --data-urlencode 'gallery_name=Test gallery'
import requests

response = requests.post(
    "https://api.pixhost.cc/galleries",
    data={"gallery_name": "Test gallery"},
    headers={"Accept": "application/json"},
    timeout=30,
)

response.raise_for_status()
print(response.json())
<?php
$curl = curl_init('https://api.pixhost.cc/galleries');
curl_setopt_array($curl, [
    CURLOPT_POST => true,
    CURLOPT_POSTFIELDS => http_build_query([
        'gallery_name' => 'Test gallery',
    ]),
    CURLOPT_HTTPHEADER => [
        'Accept: application/json',
        'Content-Type: application/x-www-form-urlencoded; charset=utf-8',
    ],
    CURLOPT_RETURNTRANSFER => true,
]);

$response = curl_exec($curl);
$status = curl_getinfo($curl, CURLINFO_HTTP_CODE);
curl_close($curl);

echo $response;

Response headers

HTTP/1.1 200 OK
Content-Type: application/json; charset=UTF-8

Response body

{
  "gallery_name": "Test gallery",
  "gallery_hash": "8NtKF",
  "gallery_url": "https://pixhost.cc/gallery/8NtKF",
  "gallery_upload_hash": "yKtOl8NbHMYJ8yWj8Mh90sIlfXC7PXT6RHW8Xua7"
}

Form Parameters

Parameter Type Required Description
gallery_name string yes Gallery name; empty is allowed for an untitled gallery, otherwise up to 255 supported Unicode characters
include_manage_url integer no Set to 1 to add a private gallery management URL to the response

Response Fields

Field Type Description
gallery_name string Gallery name
gallery_hash string Public gallery identifier
gallery_url string Public gallery URL
gallery_upload_hash string Private upload token valid for 24 hours
manage_url string Optional private gallery edit/delete URL; returned only when include_manage_url=1

Finalize the gallery after all uploads finish. Until it is finalized, the gallery and its images are not publicly available. Empty galleries are removed during finalization.

If this endpoint is not called, the current maintenance process finalizes the gallery after approximately 24 hours.

HTTP Request

POST https://api.pixhost.cc/galleries/{gallery_hash}/finalize

curl --include "https://api.pixhost.cc/galleries/8NtKF/finalize" \
  -H 'Accept: application/json' \
  --data-urlencode 'gallery_upload_hash=yKtOl8NbHMYJ8yWj8Mh90sIlfXC7PXT6RHW8Xua7'
import requests

response = requests.post(
    "https://api.pixhost.cc/galleries/8NtKF/finalize",
    data={
        "gallery_upload_hash": "yKtOl8NbHMYJ8yWj8Mh90sIlfXC7PXT6RHW8Xua7",
    },
    headers={"Accept": "application/json"},
    timeout=30,
)

response.raise_for_status()
<?php
$curl = curl_init('https://api.pixhost.cc/galleries/8NtKF/finalize');
curl_setopt_array($curl, [
    CURLOPT_POST => true,
    CURLOPT_POSTFIELDS => http_build_query([
        'gallery_upload_hash' => 'yKtOl8NbHMYJ8yWj8Mh90sIlfXC7PXT6RHW8Xua7',
    ]),
    CURLOPT_HTTPHEADER => [
        'Accept: application/json',
        'Content-Type: application/x-www-form-urlencoded; charset=utf-8',
    ],
    CURLOPT_RETURNTRANSFER => true,
]);

$response = curl_exec($curl);
$status = curl_getinfo($curl, CURLINFO_HTTP_CODE);
curl_close($curl);

Successful response

HTTP/1.1 200 OK
Content-Type: application/json; charset=UTF-8

The successful API v2 response has an empty body.

Form Parameters

Parameter Type Required Description
gallery_upload_hash string yes Private upload token returned when the gallery was created

Management

Management endpoints use the random token contained in the final path segment of manage_url. The token acts as a bearer credential. Do not log it, publish it, or send it to third-party services.

Each token contains 256 bits of cryptographically secure randomness. The server stores only its SHA-256 digest, not the token contained in the URL.

Opening manage_url in a browser only displays a confirmation page. Browser GET requests never modify or delete content.

Only gallery management tokens support rename operations. Renaming does not change the public gallery URL.

Creation and rename use identical validation. Leading and trailing whitespace is removed and repeated Unicode spaces are collapsed. Names are limited to 255 supported Unicode characters and cannot contain control/format characters, line separators, HTML angle brackets, or four-byte characters such as emoji. An empty name is valid and uses the translated untitled-gallery label.

HTTP Request

POST https://api.pixhost.cc/management/{token}/rename

curl --include "https://api.pixhost.cc/management/REPLACE_WITH_TOKEN/rename" \
  -H 'Accept: application/json' \
  --data-urlencode 'name=New gallery name'
import requests

response = requests.post(
    "https://api.pixhost.cc/management/REPLACE_WITH_TOKEN/rename",
    data={"name": "New gallery name"},
    headers={"Accept": "application/json"},
    timeout=30,
)

response.raise_for_status()
print(response.json())

Response body

{
  "success": true,
  "resource_type": "gallery",
  "gallery_name": "New gallery name",
  "gallery_url": "https://pixhost.cc/gallery/8NtKF"
}

Form Parameters

ParameterTypeRequiredDescription
namestringyesNew gallery name; an empty value restores the untitled-gallery display name, otherwise the shared 255-character policy applies

Invalid or oversized names return 422 Unprocessable Entity with a JSON error body. The endpoint reports success only after verifying that the database preserved the exact normalized value; truncation is detected as a server error.

The endpoint also accepts an application/json object containing the name field.

An image token deletes its standalone image. A gallery token deletes the gallery and all images in it.

HTTP Request

POST https://api.pixhost.cc/management/{token}/delete

curl --include -X POST \
  -H 'Accept: application/json' \
  "https://api.pixhost.cc/management/REPLACE_WITH_TOKEN/delete"
import requests

response = requests.post(
    "https://api.pixhost.cc/management/REPLACE_WITH_TOKEN/delete",
    headers={"Accept": "application/json"},
    timeout=30,
)

response.raise_for_status()
print(response.json())

Response body

{
  "success": true,
  "resource_type": "image",
  "deleted": true
}

After successful deletion the management token is revoked. Reusing it returns 410 Gone.

Errors

API v2 reports failures primarily through the HTTP status code. Image-status, management, and gallery-creation validation errors return a JSON body; other error responses can be empty, so clients must always check the status code before decoding JSON.

The 414-417 responses below are legacy API-specific codes. Their meanings differ from the standard HTTP status descriptions and are preserved for compatibility with existing API v2 clients.

Status API v2 meaning
400 Invalid request, malformed JSON, missing parameter, missing file, or unsupported endpoint
404 Management token does not exist
410 Managed content was already deleted or the management token was revoked
405 The image-status endpoint was called with a method other than POST
413 Uploaded file or image-status JSON body exceeds its configured size limit
414 Uploaded file has an unsupported image format
415 Gallery does not exist, or the image-status request is not application/json
416 Gallery upload token is incorrect
417 Gallery could not be finalized
422 Gallery name, management operation, or image-status request structure exceeds limits or is not valid
429 Image-status request rate limit exceeded; retry according to the Retry-After header
500 Internal server error

Requests rejected by upload security controls can return a plain-text message instead of JSON.