Public Storage
Vercel Blob is available on all plans
Those with the owner, member, developer role can access this feature
Public Blob stores make files accessible to anyone with the URL. Use public storage for images, videos, large media, and public assets where authentication isn't needed.
See differences with private storage.
You can create a public Blob store from the Vercel dashboard or the CLI:
- Dashboard:
- Go to your project's Storage tab
- Select Create Database, then choose Blob
- Select Continue, then set the access to Public
- CLI: Run
vercel blob create-store [name] --access public
When your code runs on Vercel, the SDK authenticates using OIDC by default. Connect your store to a project so Vercel adds the OIDC token and BLOB_STORE_ID to your environment automatically. For team-level stores or code that runs outside Vercel, see Authentication.
Upload files to a public Blob store using put() with access: 'public':
import { put } from '@vercel/blob';
export async function POST(request: Request) {
const form = await request.formData();
const file = form.get('file') as File;
const blob = await put(file.name, file, {
access: 'public',
});
return Response.json(blob);
}See the server uploads and client uploads guides for detailed instructions on uploading files.
Every file uploaded to a public Blob store gets a URL in the form of https://<store-id>.public.blob.vercel-storage.com/<pathname>. You can use this URL directly in your HTML:
<img
src="https://my-store-id.public.blob.vercel-storage.com/avatar.png"
alt="User avatar"
/>To use next/image, add the blob store hostname to your next.config.js:
/** @type {import('next').NextConfig} */
const nextConfig = {
images: {
remotePatterns: [
new URL('https://my-store-id.public.blob.vercel-storage.com/**'),
],
},
};
module.exports = nextConfig;Then use Image instead of img:
import Image from 'next/image';
<Image
src="https://my-store-id.public.blob.vercel-storage.com/avatar.png"
alt="User avatar"
width={200}
height={200}
/><a href="https://my-store-id.public.blob.vercel-storage.com/report.pdf?download=1">
Download report
</a>Adding ?download=1 to a blob URL forces a file download, regardless of file type. The SDK also exposes this as the downloadUrl property on blob objects. Without it, the URL displays the file in the browser when the MIME type supports it (images, videos, audio, PDFs, plain text, XML, and JSON). All other MIME types automatically trigger a download.
This behavior is controlled by the content-disposition header. Vercel Blob sets it to inline for displayable types and attachment for everything else. This also prevents hosting HTML pages on Vercel Blob.
When you request a public blob URL, the content is cached in two places:
- Vercel's CDN cache
- Your browser's cache
Both caches store blobs for up to 1 month by default to ensure optimal performance when serving content. While both systems aim to respect this duration, blobs may occasionally expire earlier.
Vercel will cache blobs up to 512 MB. Bigger blobs will always be served from the origin (your store).
You can customize the caching duration using the cacheControlMaxAge option in the put() and handleUpload methods.
The minimum configurable value is 60 seconds (1 minute). This represents the maximum time needed for our cache to update content behind a blob URL. For applications requiring faster updates, consider using a Vercel function instead.
See caching best practices on the overview page for guidance on updating and overwriting blobs.
When a browser requests a public blob URL, the CDN automatically includes an ETag header in the response. On subsequent requests, the browser sends an If-None-Match header with the cached ETag. If the blob hasn't changed, the CDN responds with 304 Not Modified and the browser uses its cached copy, avoiding a full re-download.
This works automatically for public blobs accessed by URL. You don't need to write any code to benefit from conditional requests.
If you're using get() to process public blobs server-side, you can also pass the ifNoneMatch option to avoid re-downloading unchanged blobs:
import { get } from '@vercel/blob';
const result = await get('images/hero.png', {
access: 'public',
ifNoneMatch: previousEtag,
});
if (result.statusCode === 304) {
// Blob hasn't changed, use the version you already have
}Anyone with the URL can request a public blob, and each download counts toward your Blob Data Transfer usage. You can control this traffic with Vercel WAF rules, such as rate limiting or IP blocking, to stop hotlinking, scraping, and abusive download patterns. To enable it:
- Open your Blob store in the dashboard and select the Settings tab.
- In the Firewall section, select Protect your store, then Enable firewall.
This connects your store to vercel-blob-default-project, a Vercel-managed, team-wide project that holds the firewall rules for all your protected Blob stores. See Firewall and WAF integration for details and limitations.
While Vercel Blob URLs can be designed to be unique and unguessable (when using addRandomSuffix: true), they can still be indexed by search engines under certain conditions:
- If you link to blob URLs from public webpages
- If you embed blob content (images, PDFs, etc.) in indexed content
- If you share blob URLs publicly, even in contexts outside your application
By default, Vercel Blob does not provide a robots.txt file or other indexing controls. This means search engines like Google may discover and index your blob content if they find links to it.
If you want to prevent search engines from indexing your blob content, you need to upload a robots.txt file directly to your blob store:
- Go to your Storage page and select your blob store
- Upload a
robots.txtfile to the root of your blob store with appropriate directives
Example robots.txt content to block all crawling of your blob store:
User-agent: *
Disallow: /
If your blob content has already been indexed by search engines:
- Verify your website ownership in Google Search Console
- Upload a
robots.txtfile to your blob store as described above - Use the "Remove URLs" tool in Google Search Console to request removal
When a public blob is downloaded, you pay for:
- Browser fetches the blob: Blob Data Transfer + Fast Origin Transfer on cache miss
Blob Data Transfer is 3x more cost-efficient than Fast Data Transfer on average, making public storage ideal for large media files like images, videos, and documents.
Blobs larger than 512 MB won't be cached, so every download is a cache miss that incurs both Blob Data Transfer and Fast Origin Transfer charges. See size limits for details.
See pricing documentation for full details.
Upload charges depend on your implementation method:
- Client Uploads: No data transfer charges for uploads
- Server Uploads: Fast Data Transfer charges apply when your Vercel application receives the file
See pricing documentation for full details.
Was this helpful?