Introduction
The PiXhost API v2 can upload images and covers, create galleries, and check the current availability of image pages.
Supported image formats:
- JPEG (
image/jpeg) - PNG (
image/png) - GIF (
image/gif) - WebP (
image/webp) - AVIF (
image/avif)
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:
https://api.pixhost.tohttps://api.pixhost.cchttps://api.pixho.st
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
- 08/12/2026 - Added batch image status checks
- 08/12/2026 - Added opt-in image and gallery management URLs
- 07/27/2026 - Documentation updated for current domains, HTTPS, WebP, and current client libraries
- 06/21/2017 - Thumbnail size range changed to 150-500 pixels
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
| Parameter | Type | Required | Description |
|---|---|---|---|
| urls | array of strings | yes | Between 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
| Status | Meaning |
|---|---|
| available | The exact image URL exists, is not deleted, and is not part of an unfinished or deleted gallery |
| deleted | The exact image URL or its gallery has been marked as deleted |
| not_found | No database record matches the complete directory and filename, or its gallery record is missing |
| pending | The image belongs to a gallery that has not yet been finalized |
| invalid | The 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:
- Create a gallery and retain both returned hashes.
- Upload images or covers with
gallery_hashandgallery_upload_hash. - Finalize the gallery.
Create 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 Gallery
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.
Rename Gallery
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
| Parameter | Type | Required | Description |
|---|---|---|---|
| name | string | yes | New 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.
Delete Image or Gallery
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.