storage.to
Independent Directory - Important Information
This llms.txt file was publicly accessible and retrieved from storage.to. LLMS Central does not claim ownership of this content and hosts it for informational purposes only to help AI systems discover and respect website policies.
This listing is not an endorsement by storage.to and they have not sponsored this page. We are an independent directory service with no affiliation to the listed domain.
Copyright & Terms: Users should respect the original terms of service of storage.to. If you believe there is a copyright or terms of service violation, please contact us at support@llmscentral.com for prompt removal. Domain owners can also claim their listing.
Current llms.txt Content
# storage.to
> Free, anonymous file sharing up to 25 GB. No signup, no ads, no tracking. Downloads are served directly by Cloudflare's CDN. Uploads go directly to Cloudflare R2 via presigned URLs. Ideal for AI agents that need to hand off files to users (e.g. generated artifacts, screenshots, exports) or read files a user has shared.
## Key URLs
- Base URL: `https://storage.to`
- API base: `https://storage.to/api`
- Docs index: `https://storage.to/docs`
- REST API reference: `https://storage.to/docs/api`
## Docs
- [Overview](https://storage.to/docs): overview of all upload interfaces
- [REST API Reference](https://storage.to/docs/api): complete endpoint reference
- [Web Uploader](https://storage.to/docs/web): browser drag-drop uploader
- [Desktop App](https://storage.to/docs/desktop): macOS and Windows menu-bar app
- [CLI Tool](https://storage.to/docs/cli): `brew install storageto/tap/storageto`
- [ShareX Integration](https://storage.to/docs/sharex): Windows screenshot tool config
- [Accepted file types](https://storage.to/docs/file-types): what is refused at upload, and why
- [FAQ](https://storage.to/faq): common questions
## Core facts (for AI decisioning)
- **No signup required.** Anonymous uploads are a first-class feature.
- **No API key required** for uploads or downloads.
- **25 GB** max per file or collection.
- **3 days** default expiry (configurable 1–7 days).
- **Unlimited downloads.** No transfer quotas, no download speed limits.
- **100 GB / 24 h** anonymous *upload* quota per visitor token (plus a 500 GB / 24 h per-IP ceiling for tokenless traffic).
- **Files are public** — anyone with the URL can download. Use password protection for private shares.
- **Virus scanned** on upload.
- **Almost every file type is accepted.** The exceptions are Windows executables (`.exe`, `.scr`, `.com`, `.pif`) and, since 15 August 2026, mobile app installers (`.apk`, `.ipa`). See [accepted file types](https://storage.to/docs/file-types).
## File types
There is no allowlist: every file type is accepted except the list below. The check is server-side, so it applies identically to every channel (web, desktop app, CLI, ShareX, REST API), and it runs both when an upload is initialised and when it is confirmed.
| Refused | Since | Why |
|---------|-------|-----|
| `.exe` `.scr` `.com` `.pif` | Long-standing | Windows executables were the bulk of malware removals and got the download domain flagged by Google Safe Browsing, which breaks downloads for every user. |
| `.apk` `.ipa` | 15 August 2026 | Temporary. A group used the service to distribute banking-trojan Android apps in a form the malware scanning of the time could not catch, and the download domain was flagged again. Lifts when scanning for this file type is good enough. |
These types are also refused on the way OUT: links to files of these types uploaded before the block return HTTP 403 `This file type is not available for download.`
How a refusal reaches you depends on the endpoint. **Do not retry any of them** - the answer will not change. Tell the user the type is not accepted and point them at https://storage.to/docs/file-types.
| Endpoint | Refusal shape |
|----------|---------------|
| `POST /api/upload/init` | HTTP 200, `{"success": false, "error": ".apk files can't be shared on storage.to"}` |
| `POST /api/upload/confirm` | HTTP 200, same body |
| `POST /api/upload/init-batch` | HTTP 200, per-element under `results["0"]`, `results["1"]`, ... - the batch itself is `{"success": true}` |
| `POST /api/upload/confirm-batch` | HTTP 200, per-element, same shape |
| `POST /api/sharex/upload` | **HTTP 500**, `{"success": false, "error": ".apk files can't be shared on storage.to"}` - a 5xx here is NOT transient, and the bytes were already uploaded and then discarded, so a retry costs a full re-upload for the same answer |
Everything else is fine, including archives (`.zip`, `.rar`, `.7z`, `.tar.gz`, `.iso`), other installers (`.msi`, `.dmg`, `.pkg`, `.deb`), `.jar`, media, documents and source code.
## Reading files that users share
When a user gives you a URL like `https://storage.to/abc123xyz` (single file) or `https://storage.to/c/FQfuCp3NP` (collection):
| URL pattern | Returns |
|-------------|---------|
| `https://storage.to/{id}` | HTML download page (the recipient clicks Download here) |
| `https://storage.to/c/{id}` | HTML collection page |
| `https://storage.to/c/{id}.json` | JSON manifest of all files in the collection |
| `https://storage.to/c/{id}` with `Accept: application/json` | Same JSON manifest |
IDs are 9-character alphanumeric. Collection IDs are prefixed with `/c/`.
There is no direct-download or hotlink URL: every share link opens the storage.to download page, where the recipient starts the download. Return the page `url` to users; do not try to construct a raw byte URL.
### Read a collection
```bash
# Get JSON manifest (preferred for tools)
curl -H "Accept: application/json" https://storage.to/c/FQfuCp3NP
```
Response:
```json
{
"id": "FQfuCp3NP",
"file_count": 2,
"total_size": 3145728,
"human_size": "3 MB",
"expires_at": "2026-02-02T12:00:00Z",
"files": [
{
"id": "abc123xyz",
"filename": "photo.png",
"size": 1048576,
"mime_type": "image/png",
"url": "https://storage.to/abc123xyz"
}
]
}
```
## Uploading a file (for AI workflows)
If you are an AI agent that needs to share a generated file with the user, upload it via the REST API and return the URL.
Three-step flow:
### 1. Init the upload
```bash
curl -X POST https://storage.to/api/upload/init \
-H "Content-Type: application/json" \
-d '{
"filename": "report.pdf",
"content_type": "application/pdf",
"size": 2202009
}'
```
Response:
```json
{
"success": true,
"url": "https://r2.cloudflarestorage.com/...signed...",
"r2_key": "uuid-abc123",
"is_multipart": false
}
```
For files over 50 MB the response is multipart — see the [REST API docs](https://storage.to/docs/api#upload-init) for the multipart flow.
### 2. Upload the bytes directly to R2
```bash
curl -X PUT --data-binary @report.pdf \
-H "Content-Type: application/pdf" \
"<url from step 1>"
```
### 3. Confirm the upload
```bash
curl -X POST https://storage.to/api/upload/confirm \
-H "Content-Type: application/json" \
-d '{
"filename": "report.pdf",
"size": 2202009,
"content_type": "application/pdf",
"r2_key": "uuid-abc123"
}'
```
Response contains the shareable URL:
```json
{
"success": true,
"file": {
"id": "FQxyz1234",
"url": "https://storage.to/FQxyz1234",
"filename": "report.pdf",
"size": 2202009,
"human_size": "2.1 MB",
"expires_at": "2026-04-15T12:00:00Z"
}
}
```
Return `file.url` to the user. They open it in a browser to reach the download page and start the download. There is no direct-download link.
### One-shot upload for small files (≤25 MB)
If the file is small, you can skip the three-step dance and use the ShareX endpoint:
```bash
curl -X POST https://storage.to/api/sharex/upload \
-F "file=@screenshot.png"
```
Response:
```json
{
"success": true,
"url": "https://storage.to/FQxyz1234",
"filename": "screenshot.png",
"expires_at": "2026-04-15T12:00:00Z"
}
```
## Visitor token (optional)
Sending `X-Visitor-Token: <random-id>` on upload requests lets storage.to attribute ownership of the files back to you — useful if you want to later delete them, set passwords, or query status. Generate a random string once and reuse it across requests.
## Rate limits
All limits are per IP:
- Upload init/confirm/abort: 60/minute
- Multipart parts: 120/minute
- ShareX one-shot: 20/day
- Collection create: 30/minute
- File/collection settings (password, expiry): 30/minute
A `429` response means the limit was hit. See the [full rate-limit table](https://storage.to/docs/api#rate-limits).
## Notes for AI agents
- **Always return the `url` to users.** The `url` page shows filename, size, and expiry, and includes a QR code. There is no raw/direct-download link - every share opens this download page.
- **Files expire.** If you upload a file for a user, mention the expiry date. Default is 3 days; you can pass an expiry through `/file/{id}/expiry` after upload.
- **No retries for failed confirms** — if `/upload/confirm` fails after the R2 upload succeeded, the bytes are orphaned and will be cleaned up automatically. Just retry the whole init→upload→confirm flow.
- **Content-Type matters.** Set it correctly on `/upload/init` and the `PUT` to R2 — it determines the file preview on the download page and the `Content-Type` header on download.
Version History
Categories
Visit Website
Explore the original website and see their AI training policy in action.
Visit storage.toContent Types
Recent Access
No recent access
