#CLI Usage with curl
A comprehensive guide to using this pastebin from the command line. For the full HTTP API reference, see api.md.
#Conventions
<name>— the random name (e.g.abcd) or custom name (prefixed with~, e.g.~hitagi) of a paste.<passwd>— the password returned at upload time, used to update or delete the paste.<expire>— an expiration period: an integer or float, optionally suffixed withs(seconds, default),m(minutes),h(hours), ord(days). For example,300,30m,25d.
#Uploading
#Upload text content
$ curl -Fc='hello, world' https://shz.al
{
"url": "https://shz.al/abcd",
"manageUrl": "https://shz.al/abcd:w2eHqyZGc@CQzWLN=BiJiQxZ",
"expirationSeconds": 1209600,
"expireAt": "2026-05-21T10:33:06.114Z"
}
Save url for sharing and manageUrl for later updates or deletion.
#Upload a file
$ curl -Fc=@panty.jpg https://shz.al
The original filename will be sent back as the Content-Disposition header
when the paste is fetched.
#Upload from stdin
$ echo 'hello' | curl -Fc=@- https://shz.al
$ cat panty.jpg | curl -Fc=@- https://shz.al
#Set an expiration
$ curl -Fc='kawaii' -Fe=300 https://shz.al # 300 seconds
$ curl -Fc='kawaii' -Fe=2h https://shz.al # 2 hours
$ curl -Fc=@big.bin -Fe=30d https://shz.al # 30 days
If e is not specified, the default expiration of the deployment is used. The
maximum expiration is also enforced by the deployment.
#Use a custom name
$ curl -Fc='kawaii' -Fn=hitagi https://shz.al
{
"url": "https://shz.al/~hitagi",
...
}
The custom name is at least 3 characters long and may consist of letters,
digits, and +_-[]*$=@,;/. Note the leading ~ in the returned URL.
Because curl uses ; and , as field separators, names containing those
characters need to be wrapped in extra quotes:
$ curl -Fc=@panty.jpg -Fn='"hi/hello;g,ood"' https://shz.al
#Set a custom password
$ curl -Fc='kawaii' -Fs=12345678 https://shz.al
If s is omitted, a random password is generated and returned in manageUrl.
#Private mode (longer random name)
$ curl -Fc='secret' -Fp=1 https://shz.al
Without a custom name (n), p produces a 24-character random name, making
the paste effectively unguessable.
#Mark a paste as syntax-highlighted
$ curl -Fc=@main.rs -Flang=rust https://shz.al
The lang field is sent back as the X-PB-Highlight-Language header on
fetching the paste, and is used by the display page (/d/<name>).
#Fetching
#Fetch raw content
$ curl https://shz.al/abcd
hello, world
#Save the response to a file
$ curl https://shz.al/~panty.jpg -o panty.jpg
$ curl -OJ https://shz.al/~panty # use server-supplied filename
-J honors the Content-Disposition header set from the original filename.
#Force download (attachment)
$ curl 'https://shz.al/abcd?a' -OJ
The ?a query string sets Content-Disposition: attachment.
#Override mime type
$ curl 'https://shz.al/~panty.jpg?mime=image/png' \
-w '%{content_type}\n' -o /dev/null -sS
image/png
Or via path extension:
$ curl 'https://shz.al/abcd.json' -i
#Pipe to another tool
$ curl https://shz.al/~panty.jpg | feh -
$ curl https://shz.al/~config | jq .
#Conditional fetch with If-Modified-Since
$ curl -i -H 'If-Modified-Since: Wed, 01 May 2026 00:00:00 GMT' \
https://shz.al/~hitagi
HTTP/2 304
#Inspecting metadata
$ curl https://shz.al/m/abcd
{
"lastModifiedAt": "2026-05-05T10:33:06.114Z",
"createdAt": "2026-05-01T10:33:06.114Z",
"expireAt": "2026-05-08T10:33:06.114Z",
"sizeBytes": 4096,
"location": "KV",
"filename": "a.jpg"
}
A HEAD request returns the same headers as GET without the body, useful
for quickly checking size and Content-Type:
$ curl -I https://shz.al/abcd
#URL shortener
Upload a short URL, then redirect through /u/<name>:
$ curl -Fc='https://example.com/very/long/path' -Fn=ex https://shz.al
$ curl -L https://shz.al/u/~ex
#Markdown rendering
Upload a markdown file and render it as HTML via /a/<name>:
$ curl -Fc=@README.md -Fn=readme https://shz.al
$ firefox https://shz.al/a/~readme
GitHub-flavored Markdown is supported, along with syntax highlighting and LaTeX math via MathJax.
#Updating an existing paste
Use the manageUrl returned at upload time:
$ curl -X PUT -Fc='kawaii~' \
https://shz.al/~hitagi:22@-OJWcTOH2jprTJWYadmDv
PUT accepts the same fields as POST (c, e, s). Note that e
recalculates the expiration starting from the update time.
#Deleting a paste
$ curl -X DELETE https://shz.al/~hitagi:22@-OJWcTOH2jprTJWYadmDv
the paste will be deleted in seconds
Deletion may take a few seconds to propagate globally.
#Tips
Pipe long output through
jqto inspect upload responses:$ curl -sFc='hi' https://shz.al | jq -r .urlSave the management URL into a variable to chain commands:
$ resp=$(curl -sFc=@notes.md https://shz.al) $ url=$(jq -r .url <<<"$resp") $ mgmt=$(jq -r .manageUrl <<<"$resp")For files larger than the
R2_THRESHOLDof the deployment, content is stored in R2 instead of KV transparently — no client change is needed.The maximum allowed upload size is set per deployment via
R2_MAX_ALLOWED. Exceeding it returns HTTP413.A single HTTP request body is capped at 100 MB by Cloudflare Workers (HTTP
413 Payload Too Largeis returned before the request ever reaches the worker), regardless of the deployment'sR2_MAX_ALLOWED. To upload larger files, use the web UI athttps://shz.alor thepbCLI — both automatically switch to a multipart upload that streams 5 MiB chunks through the/mpu/*endpoints.
#Common errors
| Status | Meaning |
|---|---|
400 |
Malformed request (bad field, illegal name, bad expire). |
403 |
Wrong password when updating or deleting. |
404 |
Paste not found, or already expired. |
409 |
Custom name is already in use. |
413 |
Request body exceeds 100 MB (platform cap, intercepted by Cloudflare before reaching the worker), or content exceeds the deployment's R2_MAX_ALLOWED. |
500 |
Unexpected server error — please report it. |
For the full HTTP API including HEAD, OPTIONS, response headers, and edge
cases, see api.md.