Skip to content

Upload API

The Upload API allows uploading files to CloudFlare ImgBed from third-party applications and services.

Basic Information

  • Endpoint: /upload
  • Method: POST
  • Authentication: Upload auth code or API Token (requires upload permission)
  • Content Type: multipart/form-data

Response Format

json
[{ "src": "/file/abc123_image.jpg" }]

src does not include the domain — prepend it yourself. Use returnFormat=full for full URLs.

Basic Upload

Upload a file directly via the /upload endpoint. Suitable for small files.

Parameters

Query Parameters:

ParameterTypeRequiredDefaultDescription
authCodestringNo-Upload authentication code
uploadChannelstringNotelegramStorage channel: telegram, cfr2, s3, discord, huggingface, webdav
channelNamestringNo-Specific channel name (multi-channel scenarios). Get available list via /api/channels
serverCompressbooleanNotrueServer-side compression (Telegram channel images only)
autoRetrybooleanNotrueAuto-retry with another channel on failure
uploadNameTypestringNodefaultNaming: default (prefix_original), index (prefix only), origin (original only), short (short link)
returnFormatstringNodefaultResponse format: default (/file/id), full (full URL)
uploadFolderstringNo-Upload directory, relative path, e.g. img/test

Body Parameters (FormData):

ParameterTypeRequiredDescription
fileFileYesFile to upload

Example

bash
curl -X POST 'https://your.domain/upload?authCode=YOUR_CODE&uploadChannel=telegram' \
  -F 'file=@"/path/to/image.jpg"'

File Size Limits

  • Cloudflare Pages deployment: max request body 100MB
  • Telegram channel: single file max 20MB (auto server-side chunking beyond this)
  • Discord channel: free 10MB / Nitro 25MB
  • HuggingFace channel: basic upload proxied through backend, limited by CF Workers CPU time. Use direct upload for large files (see below)

Chunked Upload (Telegram / R2 / S3 / Discord)

For large files, the client splits the file into chunks, uploads them individually, then requests the server to merge. Supported for telegram, cfr2, s3, and discord channels.

HuggingFace does NOT support chunked upload

HuggingFace has its own direct upload flow for large files. See HuggingFace Direct Upload below.

ChannelRecommended SizeNotes
telegram16MBTelegram Bot getFile download limit is 20MB, 4MB safety margin
cfr2 / s35MB - 20MBFollows S3 Multipart Upload spec, minimum 5MB
discord8MBFree user limit is 10MB, leave margin

Upload Flow

Chunked upload has three steps: Initialize → Upload Chunks → Merge.

Step 1: Initialize

Create an upload session and obtain an uploadId.

Query Parameters:

ParameterTypeRequiredDescription
authCodestringNoUpload authentication code
initChunkedbooleanYesSet to true
uploadChannelstringNoStorage channel: telegram, cfr2, s3, discord
channelNamestringNoSpecific channel name (multi-channel scenarios). Get available list via /api/channels

Body Parameters (FormData):

ParameterTypeRequiredDescription
originalFileNamestringYesOriginal file name
originalFileTypestringYesOriginal file MIME type
totalChunksintegerYesTotal number of chunks

Request Example:

POST /upload?authCode=YOUR_CODE&initChunked=true&uploadChannel=telegram
Content-Type: multipart/form-data

FormData:
  originalFileName: "video.mp4"
  originalFileType: "video/mp4"
  totalChunks: 5

Response Example:

json
{
  "success": true,
  "uploadId": "upload_1713500000000_abc123def",
  "sessionInfo": {
    "uploadId": "upload_1713500000000_abc123def",
    "originalFileName": "video.mp4",
    "totalChunks": 5,
    "uploadChannel": "telegram"
  }
}

Step 2: Upload Chunks

Split the file by the recommended chunk size and upload each chunk. Each request is synchronous — the server waits for the chunk to be stored before responding.

Query Parameters:

ParameterTypeRequiredDescription
authCodestringNoUpload authentication code
chunkedbooleanYesSet to true
uploadChannelstringNoStorage channel: telegram, cfr2, s3, discord
channelNamestringNoSpecific channel name (multi-channel scenarios). Get available list via /api/channels

Body Parameters (FormData):

ParameterTypeRequiredDescription
fileFileYesChunk binary data
uploadIdstringYesUpload session ID from initialization
chunkIndexintegerYesChunk index, 0-based
totalChunksintegerYesTotal number of chunks
originalFileNamestringYesOriginal file name
originalFileTypestringYesOriginal file MIME type

Request Example:

POST /upload?authCode=YOUR_CODE&chunked=true&uploadChannel=telegram
Content-Type: multipart/form-data

FormData:
  file: <chunk binary data>
  uploadId: "upload_1713500000000_abc123def"
  chunkIndex: 0
  totalChunks: 5
  originalFileName: "video.mp4"
  originalFileType: "video/mp4"

Response Example:

json
{
  "success": true,
  "message": "Chunk 1/5 received and being uploaded",
  "uploadId": "upload_1713500000000_abc123def",
  "chunkIndex": 0
}

Concurrent Uploads

Chunks can be uploaded concurrently for better speed. For R2/S3 channels, the first chunk (chunkIndex=0) initializes the Multipart Upload; other chunks automatically wait for initialization (up to 60 seconds).

Step 3: Merge

After all chunks are uploaded, request a merge. The merge process is synchronous.

Query Parameters:

ParameterTypeRequiredDescription
authCodestringNoUpload authentication code
chunkedbooleanYesSet to true
mergebooleanYesSet to true
uploadChannelstringNoStorage channel: telegram, cfr2, s3, discord
channelNamestringNoSpecific channel name (multi-channel scenarios). Get available list via /api/channels
returnFormatstringNoResponse format: default (/file/id), full (full URL)
uploadFolderstringNoUpload directory, relative path, e.g. img/test

Body Parameters (FormData):

ParameterTypeRequiredDescription
uploadIdstringYesUpload session ID
totalChunksintegerYesTotal number of chunks
originalFileNamestringYesOriginal file name
originalFileTypestringYesOriginal file MIME type

Request Example:

POST /upload?authCode=YOUR_CODE&chunked=true&merge=true&uploadChannel=telegram
Content-Type: multipart/form-data

FormData:
  uploadId: "upload_1713500000000_abc123def"
  totalChunks: 5
  originalFileName: "video.mp4"
  originalFileType: "video/mp4"

Response Example:

json
[{ "src": "/file/1713500000000_video.mp4" }]

Failure Retry

During merge, the server automatically checks chunk statuses and retries failed/timed-out chunks (up to 5 times). If chunks remain incomplete, the merge returns an error.

Cleanup Request

To cancel an in-progress upload and release temporary data.

Query Parameters:

ParameterTypeRequiredDescription
authCodestringNoUpload authentication code
cleanupbooleanYesSet to true
uploadIdstringYesUpload session ID
totalChunksintegerYesTotal number of chunks
POST /upload?authCode=YOUR_CODE&cleanup=true&uploadId=xxx&totalChunks=5

HuggingFace Direct Upload

The HuggingFace channel uses a dedicated upload flow where the client uploads directly to HuggingFace LFS storage. CF Workers only handle signing and committing, bypassing Cloudflare's 100MB request body limit and CPU time constraints.

Choosing Upload Method

ScenarioMethodNotes
Small files (< 20MB)Basic upload /upload?uploadChannel=huggingfaceFile proxied through backend
Large files (≥ 20MB)Direct upload (3 steps)Client uploads directly to HuggingFace S3

Direct Upload Flow

Prerequisites

The client must pre-compute:

  • SHA-256: Full file content SHA-256 hash (hex string)
  • fileSample: Base64 encoding of the first 512 bytes

Step 1: Get Upload URL

Request Parameters (JSON Body):

ParameterTypeRequiredDescription
fileNamestringYesFile name
fileTypestringYesFile MIME type
fileSizeintegerYesFile size in bytes
sha256stringYesFile SHA-256 hash (hex)
fileSamplestringYesBase64 of first 512 bytes
channelNamestringNoSpecific channel name (multi-channel scenarios). Get available list via /api/channels
uploadNameTypestringNoNaming: default (prefix_original), index (prefix only), origin (original only), short (short link)
uploadFolderstringNoUpload directory, relative path, e.g. img/test

Request Example:

POST /upload/huggingface/getUploadUrl
Content-Type: application/json
Authorization: Bearer <API_TOKEN>

{
  "fileName": "large-video.mp4",
  "fileType": "video/mp4",
  "fileSize": 524288000,
  "sha256": "e3b0c44298fc1c149afbf4c8996fb924...",
  "fileSample": "AAAAIGZ0eXBpc29t...",
  "channelName": "my-hf-channel",
  "uploadNameType": "default",
  "uploadFolder": "videos"
}

Response Example:

json
{
  "success": true,
  "fullId": "videos/1713500000000_large-video.mp4",
  "filePath": "videos/a1b2c3d4_1713500000000_large-video.mp4",
  "channelName": "my-hf-channel",
  "repo": "username/repo-name",
  "needsLfs": true,
  "alreadyExists": false,
  "oid": "e3b0c44298fc1c149afbf4c8996fb924...",
  "uploadAction": {
    "href": "https://s3.amazonaws.com/...",
    "header": { ... }
  }
}

Key fields:

  • needsLfs: false — file doesn't need LFS (tiny text files), skip to Step 3
  • alreadyExists: true — file already in LFS, skip Step 2 and go to Step 3
  • uploadAction.header.chunk_size — if present, HuggingFace requires multipart upload; zoro-padding numeric keys ("00001", "00002", ...) in header are pre-signed URLs for each part

Step 2: Upload File to HuggingFace S3

Upload directly to HuggingFace S3 storage using the uploadAction info.

Basic upload (no chunk_size):

PUT <uploadAction.href>
Headers: <uploadAction.header>
Body: <file binary content>

Multipart upload (has chunk_size):

Split the file by chunk_size, PUT each part to header["00001"], header["00002"], etc., collecting the ETag from each response. After all parts are uploaded, complete the upload:

POST <uploadAction.href>
Content-Type: application/vnd.git-lfs+json

{
  "oid": "<sha256>",
  "parts": [
    { "partNumber": 1, "etag": "\"abc123\"" },
    { "partNumber": 2, "etag": "\"def456\"" }
  ]
}

Step 3: Commit File Reference

After upload, call the commit endpoint to register the file in the system database.

Request Parameters (JSON Body):

ParameterTypeRequiredDescription
fullIdstringYesFile ID from Step 1
filePathstringYesStorage path from Step 1
sha256stringYesFile SHA-256 hash (hex)
fileSizeintegerYesFile size in bytes
fileNamestringNoFile name
fileTypestringNoFile MIME type
channelNamestringNoSpecific channel name (multi-channel scenarios). Get available list via /api/channels

Request Example:

POST /upload/huggingface/commitUpload
Content-Type: application/json
Authorization: Bearer <API_TOKEN>

{
  "fullId": "videos/1713500000000_large-video.mp4",
  "filePath": "videos/a1b2c3d4_1713500000000_large-video.mp4",
  "sha256": "e3b0c44298fc1c149afbf4c8996fb924...",
  "fileSize": 524288000,
  "fileName": "large-video.mp4",
  "fileType": "video/mp4",
  "channelName": "my-hf-channel"
}

Response Example:

json
{
  "success": true,
  "src": "/file/videos/1713500000000_large-video.mp4",
  "fileUrl": "https://huggingface.co/datasets/username/repo-name/resolve/main/videos/a1b2c3d4_1713500000000_large-video.mp4",
  "fullId": "videos/1713500000000_large-video.mp4"
}

Flow Summary

HF Direct Upload Demo

Released under the MIT License