#HTTP API Reference
#GET /
Return the index page.
#GET /<name>[.<ext>] or /<name>/<filename>
Fetch the paste with name <name>. By default, it will return the raw content of the paste.
The Content-Type header is set to the mime type inferred from the filename of the paste, or text/plain;charset=UTF-8 if no filename is present. If <ext> is given, the worker will infer mime-type from <ext> and change Content-Type. If the paste is uploaded with a filename, the worker will infer mime-type from the filename. This method accepts the following query string parameters:
The Content-Disposition header is set to inline by default. But can be overriden by ?a query string. If the paste is uploaded with filename, or <filename> is set in given request URL, Content-Disposition is appended with filename* indicating the filename. If the paste is encrypted, the filename is appended with .encrypted suffix.
If the paste is encrypted, an X-PB-Encryption-Scheme header will be set to the encryption scheme. An X-PB-Decrypted-Content-Type header is also set to the mime type that the decrypted content would have (inferred from the same sources as Content-Type but ignoring the encryption-induced application/octet-stream fallback), so clients can decide how to render the plaintext without an extra round trip.
If the paste is uploaded with a lang parameter, an X-PB-Highlight-Language header will be set to the highlight language.
?a=: optional. SetContent-Dispositiontoattachmentif present.?mime=<mime>: optional. Specify the mime-type, suppressing the effect of<ext>. No effect iflangis specified (in which case the mime-type is alwaystext/html).
Examples: GET /abcd?lang=js, GET /abcd?mime=application/json.
If error occurs, the worker returns status code different from 200:
404: the paste of given name is not found.500: unexpected exception. You may report this to the author to give it a fix.
#GET /<name>:<passwd>
Return the web page to edit the paste of name <name> and password <passwd>.
If error occurs, the worker returns status code different from 200:
404: the paste of given name is not found.500: unexpected exception. You may report this to the author to give it a fix.
#GET /u/<name>
Redirect to the URL recorded in the paste of name <name>.
If error occurs, the worker returns status code different from 302:
404: the paste of given name is not found.500: unexpected exception. You may report this to the author to give it a fix.
#GET /d/<name>[.<ext>] or /d/<name>/<filename>
Return the web page that will display the content of the paste of name <name>. If the paste is encrypted, a key can be appended to the URL to decrypt the paste of name <name> in browser.
If error occurs, the worker returns status code different from 200:
404: the paste of given name is not found.500: unexpected exception. You may report this to the author to give it a fix.
#GET /m/<name>
Get the metadata of the paste of name <name>.
If error occurs, the worker returns status code different from 200:
404: the paste of given name is not found.500: unexpected exception. You may report this to the author to give it a fix.
The response body is a JSON object, for example:
{
"lastModifiedAt": "2025-05-05T10:33:06.114Z",
"createdAt": "2025-05-01T10:33:06.114Z",
"expireAt": "2025-05-08T10:33:06.114Z",
"sizeBytes": 4096,
"location": "KV",
"filename": "a.jpg",
"highlightLanguage": "rust",
"encryptionScheme": "AES-GCM"
}
Explanation of the fields:
lastModifiedAt: String. An ISO String representing the last modification time of the paste.expireAt: String. An ISO String representing when the paste will expire.createdAt: String. An ISO String representing when the paste was created.sizeBytes: Integer. The size of the content of the paste in bytes.filename: Optional string. The file name of the paste.location: String, either "KV" or "R2". Representing whether the paste content is stored in Cloudflare KV storage or R2 object storage.highlightLanguage: Optional string. The syntax highlighting language uploaded with thelangform field.encryptionScheme: Optional string. Currently only "AES-GCM" is possible. The encryption scheme used to encrypt the paste.
#GET /a/<name>
Return the HTML converted from the markdown file stored in the paste of name <name>. The markdown conversion follows GitHub Flavored Markdown (GFM) Spec, supported by remark-gfm.
Syntax highlighting is supported by prism.js. LaTeX mathematics is supported by MathJax.
If the paste is encrypted, the server cannot read it, so it returns a page without content, and the browser fetches the paste, decrypts it with the key in the URL fragment, and renders it. Open it as /a/<name>#<key>, or as /a/<name>#<key>:<section> to jump to the heading with id <section> (percent-encoded). Links inside the rendered page keep the key in the same way. See https://pastebin.doesthis.help/doc/paste-crypto.
If error occurs, the worker returns status code different from 200:
404: the paste of given name is not found.500: unexpected exception. You may report this to the author to give it a fix.
Usage example:
# Header 1
This is the content of `test.md`
<script>
alert("Script should be removed")
</script>
## Header 2
| abc | defghi |
| :-: | -----: |
| bar | baz |
**Bold**, `Monospace`, _Italics_, ~~Strikethrough~~, [URL](https://github.com)
- A
- A1
- A2
- B

1. first
2. second
> Quotation
$$
\int_{-\infty}^{\infty} e^{-x^2} = \sqrt{\pi}
$$
#HEAD /*
Request a paste without returning the body. It accepts same parameters as all GET requests, and returns the same Content-Type, Content-Disposition, Content-Length and cache control headers with the corresponding GET request. Note that the Content-Length with /a/<name>, ?lang=<lang> is the length of the paste instead of the length of the actual HTML page.
#POST /
Upload your paste. It accept parameters in form-data:
c: mandatory. The content of your paste, text or binary. The maximum allowed size is set by the deployment (R2_MAX_ALLOWED). Thefilenamein itsContent-Dispositionwill be present when fetching the paste. Note that a single Cloudflare Workers request body is capped at 100 MB — request bodies larger than that are rejected by the platform with HTTP413 Payload Too Largebefore the worker is invoked. For larger files, use the official web UI at/or thepbCLI, which transparently chunk the content via the multipart-upload endpoints.e: optional. The expiration time of the paste. After this period of time, the paste is permanently deleted. It should be an integer or a float point number suffixed with an optional unit (seconds by default). Supported units:s(seconds),m(minutes),h(hours),d(days). For example,360.25means 360.25 seconds, and25dmeans 25 days. The actual expiration might be shorter than specified expiration due to limitations imposed by the administrator. If unspecified, a default expiration time setting is used.s: optional. The password which allows you to modify and delete the paste. If not specified, the worker will generate a random string as password.n: optional. The customized name of your paste. If not specified, the worker will generate a random string (4 characters by default) as the name. You need to prefix the name with~when fetching the paste of customized name. The name is at least 3 characters long, consisting of alphabet, digits and characters in+_-[]*$=@,;/.p: optional. The flag of private mode. If specified to any value, the name of the paste is as long as 24 characters. No effect ifnis used.encryption-scheme: optional. The encryption scheme used in the uploaded paste. It will be returned asX-PB-Encryption-Schemeheader on fetching paste. Note that this is not the encryption scheme that the backend will perform. See https://pastebin.doesthis.help/doc/paste-crypto for how clients encrypt pastes.lang: optional. The language of the uploaded paste for syntax highlighting. Should be a lower-case name of language listed in highlight.js documentation. This will be returned asX-PB-Highlight-Languageheader on fetching paste.
POST method returns a JSON string by default, if no error occurs, for example:
{
"url": "https://shz.al/abcd",
"manageUrl": "https://shz.al/abcd:w2eHqyZGc@CQzWLN=BiJiQxZ",
"expirationSeconds": 1209600,
"lastModifiedAt": "2025-05-01T10:33:06.114Z",
"createdAt": "2025-05-01T10:33:06.114Z",
"expireAt": "2025-05-05T10:33:06.114Z",
"sizeBytes": 4096,
"location": "KV",
"filename": "a.jpg",
"highlightLanguage": "rust",
"encryptionScheme": "AES-GCM"
}
Explanation of the fields:
url: String. The URL to fetch the paste. When using a customized name, it looks likehttps://shz.al/~myname.manageUrl: String. The URL to update and delete the paste, which isurlsuffixed by:and the password.expirationSeconds: Number. The expiration seconds.
The remaining fields mirror the GET /m/<name> metadata response: lastModifiedAt, createdAt, expireAt, sizeBytes, location, and the optional filename, highlightLanguage, encryptionScheme.
If error occurs, the worker returns status code different from 200:
400: your request is in bad format.409: the name is already used.413: the request body exceeds Cloudflare's 100 MB per-request cap (returned by the platform before the worker runs), or the content exceeds the deployment'sR2_MAX_ALLOWED.500: unexpected exception. You may report this to the author to give it a fix.
#PUT /<name>:<passwd>
Update your paste of the name <name> and password <passwd>. It accepts all the same form-data fields as POST (c, e, s, lang, encryption-scheme) except n (the name cannot be changed; supplying it returns 400) and p (silently ignored). When e is supplied, the expiration is recalculated from the update time.
The returning of PUT method is the same as POST method.
If error occurs, the worker returns status code different from 200:
400: your request is in bad format.403: your password is not correct.404: the paste of given name is not found.413: the request body exceeds Cloudflare's 100 MB per-request cap (returned by the platform before the worker runs), or the content exceeds the deployment'sR2_MAX_ALLOWED.500: unexpected exception. You may report this to the author to give it a fix.
#DELETE /<name>:<passwd>
Delete the paste of name <name> and password <passwd>. It may take seconds to synchronize the deletion globally.
If error occurs, the worker returns status code different from 200:
403: your password is not correct.404: the paste of given name is not found.500: unexpected exception. You may report this to the author to give it a fix.
#GET /live
Return the live pastebin page. Everyone who opens the same /live#<key> URL joins one channel, where posts (text with an optional filename and highlight language, or files up to 10 MiB) show up on every open page immediately. <key> is 32 random bytes in base64 (with / replaced by _ and padding removed); a fresh one is generated if the fragment is empty.
The key never reaches the server. Each open page makes an ephemeral key pair, exchanges public keys with the other pages in the channel, and encrypts every post separately for the pages that are open at the time, so a recorded post cannot be decrypted later even with the link. Nothing is stored anywhere: a page only shows posts made while it is open. See https://pastebin.doesthis.help/doc/live-crypto for the cryptographic design and its analysis.
Nicknames are not authenticated: anyone with the link can post under any nickname and timestamp. Since posts come from other people, the page treats them as untrusted: markdown is sanitized more strictly than on /a/<name> (no custom classes, ids, form controls or remote images), text over 512 KiB and images other than PNG, JPEG, GIF, WebP, AVIF and BMP (including SVG) are only offered for download.
/live takes precedence over a paste named live, which can still be read through /d/live or /m/live. Random paste names never collide with it. If BASIC_AUTH is configured, both /live and /live/ws/<channel-id> require it.
#GET /live/ws/<channel-id>
WebSocket endpoint that relays posts between peers in the channel <channel-id>, which must be 32 lowercase hex characters.
- Binary frames carry key exchange messages and posts. A frame sent by a client is forwarded as is to all other peers in the channel. The server cannot read it; the format is described in https://pastebin.doesthis.help/doc/live-crypto.
- Text frames sent by the server are control messages:
{"t":"peers","n":<count>}whenever someone joins or leaves, and{"t":"error","msg":...}when a frame is dropped. A text framepingsent by a client is answered withpong; other text frames from clients are dropped.
A post body is at most 10 MiB, and frames larger than that plus 64 KiB close the connection with code 1009. Frames are rate limited by size, both per connection (24 MiB burst, then 1 MiB/s) and per channel (48 MiB burst, then 4 MiB/s); frames over the limit are dropped with an error message.
If error occurs, the worker returns status code different from 101:
400: the channel id is illegal.426: the request is not a WebSocket upgrade.503: the channel already has 64 peers.