The Vercel Blob JavaScript API client
Last release 17 days ago
10 Aug 2026
Ships fairly regularly
a new release about every 2 weeks
Nearly every release is documented
notes for 59 of the last 60 stable releases
Nothing withdrawn
no release was ever pulled
3 years old
179 releases · first in 2023
Release timeline
179 releases since 2023Releases
- 2.8.010 Aug 2026
Release notes
Open source →Minor Changes
- 8b49164: Add
putImage(pathname, bodyOrUrl, options): optimizes an image through Vercel Image Optimization and stores only the optimized output. The source can be the image content itself (string, File, Blob, Buffer or Stream) or aURLinstance pointing at a public http(s) image, which is fetched server-side. Options mirrorput(access, addRandomSuffix, allowOverwrite, cacheControlMaxAge, ifMatch) plus the requiredoptimizeImageparameters (width,quality,format);contentTypeis not accepted since the stored content type always comes from the optimizer output. Deprecates theoptimizeImageoption onputand theputFromUrlfunction in favor ofputImage; both keep working.
- 8b49164: Add
- 2.8.0-76c89fb-2026081018441110 Aug 2026pre-release
Nothing published for this version
- 2.7.06 Aug 2026
Release notes
Open source →Minor Changes
-
ad5a134: Add image optimization support: a new
optimizeImageoption onputand a newputFromUrlmethod. Both optimize the image through Vercel Image Optimization before storing it (only the optimized output is stored) and require OIDC authentication.const result = await put("avatars/foo.webp", body, { access: "public", optimizeImage: { width: 128, quality: 75, format: "webp" }, }); const result = await putFromUrl( "avatars/foo.webp", "https://example.com/photo.jpg", { access: "public", optimizeImage: { width: 128, quality: 75, format: "webp" }, } );
-
- 2.7.0-ad5a134-202608051934095 Aug 2026pre-release
Nothing published for this version
- 2.6.18 Jul 2026
Release notes
Open source →Patch Changes
- d0118c4: Add a
useCacheoption topresignUrl()forgetoperations. WhenuseCache: false, the presigned URL includes acache=0query param so fetches bypass the CDN cache and read the latest content directly from origin storage. Likeget(), the bypass only applies to private blobs. The param is not part of the signed payload, so holders of a presigned URL can also add or remove it manually.
- d0118c4: Add a
- 2.6.07 Jul 2026
Release notes
Open source →Minor Changes
- c4976ba: Add
rename(fromUrlOrPathname, toPathname, options)to move a blob to another pathname. The blob is copied to the new pathname and the source is deleted afterwards; if the copy fails the source is left untouched. By default renaming onto an existing blob throws — passallowOverwrite: trueto replace it, oraddRandomSuffix: trueto generate a unique destination. Requires a read-write token (client tokens are not supported). - 89d94e9: Restore the
useCacheoption onget(). PassinguseCache: falsebypasses the CDN cache and serves the blob directly from origin storage (via thecache=0query parameter), guaranteeing the latest content at the cost of slower reads. Defaults totrue.
- c4976ba: Add
- 2.5.025 Jun 2026
Release notes
Open source →Minor Changes
- 31a8b8f: Deprecate the
useCacheoption onget(). The backend no longer honors thecache=0query parameter it produced, so the option is now a no-op — reads always go through the standard caching path. The option is still accepted (and ignored) to avoid breaking existing callers, and will be removed in a future major version.
Patch Changes
- 9ac2586: Read the Vercel OIDC token via
@vercel/oidc's refreshinggetVercelOidcTokeninstead of the non-refreshinggetVercelOidcTokenSync. This refreshes an expired token in development environments. In production with a valid token, behavior is unchanged. If a refresh is needed but fails, the token is treated as absent so callers still fall back toBLOB_READ_WRITE_TOKEN.
- 31a8b8f: Deprecate the
- 2.4.2-4f3596e-2026062512535725 Jun 2026pre-release
Nothing published for this version
- 2.4.118 Jun 2026
Release notes
Open source →Patch Changes
- b7027de: Read the Vercel OIDC token via the
@vercel/oidcpackage (getVercelOidcTokenSync) instead of an inlined copy. This makes the dependency explicit and discoverable, and matches how other Vercel packages consume OIDC. Behavior is unchanged except for one edge case: a blankx-vercel-oidc-tokenrequest-context header now resolves to no token rather than falling back toVERCEL_OIDC_TOKEN.
- b7027de: Read the Vercel OIDC token via the
- 2.4.1-b7027de-2026061619305616 Jun 2026pre-release
Nothing published for this version
- 2.4.018 May 2026
- 2.3.4-dfec20e-2026043022295430 Apr 2026pre-release
Nothing published for this version
- 2.3.4-c199a29-2026051517344115 May 2026pre-release
Nothing published for this version
- 2.3.4-ac3f656-202605062200256 May 2026pre-release
Nothing published for this version
- 2.3.4-abeb564-202605051739505 May 2026pre-release
Nothing published for this version
- 2.3.4-a659982-202605062220046 May 2026pre-release
Nothing published for this version
- 2.3.4-a65182b-202605061639496 May 2026pre-release
Nothing published for this version
- 2.3.4-a5ceef9-202605070436567 May 2026pre-release
Nothing published for this version
- 2.3.4-9a55b7d-202605062243236 May 2026pre-release
Nothing published for this version
- 2.3.4-9a05ef7-202605071755577 May 2026pre-release
Nothing published for this version
- 2.3.4-916b4c4-202605062305166 May 2026pre-release
Nothing published for this version
- 2.3.4-8b17a14-202605071804227 May 2026pre-release
Nothing published for this version
- 2.3.4-83f2da4-202605052023445 May 2026pre-release
Nothing published for this version
- 2.3.4-6010219-202605062300456 May 2026pre-release
Nothing published for this version
- 2.3.4-5d06fa0-2026042821521728 Apr 2026pre-release
Nothing published for this version
- 2.3.4-52fd7bc-202605070003187 May 2026pre-release
Nothing published for this version
- 2.3.4-4cd4da4-202605062232356 May 2026pre-release
Nothing published for this version
- 2.3.4-40fd456-202605052016355 May 2026pre-release
Nothing published for this version
- 2.3.4-1ce589e-202605062008146 May 2026pre-release
Nothing published for this version
- 2.3.4-1a02707-202605041807534 May 2026pre-release
Nothing published for this version
- 2.3.4-179061a-2026042821061428 Apr 2026pre-release
Nothing published for this version
- 2.3.4-128dc33-202605062345166 May 2026pre-release
Nothing published for this version
- 2.3.4-05eb596-202605062247456 May 2026pre-release
Nothing published for this version
- 2.3.32 Apr 2026
Release notes
Open source →Patch Changes
- d2ea7cf: Enforce
maximumSizeInBytesclient-side for multipart uploads. Bodies with a known size (Blob, File, Buffer) are now checked before the upload starts, avoiding wasted API calls. - 949e994: Fix multipart upload hanging forever on empty streams, and fix
createChunkTransformStreambypassing backpressure by removing incorrectqueueMicrotaskwrapping.
- d2ea7cf: Enforce
- 2.3.3-f8b7d06-202604021400072 Apr 2026pre-release
Nothing published for this version
- 2.3.3-f13c642-202604021328392 Apr 2026pre-release
Nothing published for this version
- 2.3.227 Mar 2026
Release notes
Open source →Patch Changes
- c9d9a1a: Apply
ifMatch/allowOverwritevalidation tohandleUploadandgenerateClientTokenFromReadWriteToken. WhenifMatchis set viaonBeforeGenerateTokenor direct token generation,allowOverwriteis now implicitly enabled. Explicitly passingallowOverwrite: falsewithifMatchthrows a clear error. - 6dcecb8: Make
ifMatchimplyallowOverwrite: trueonput(). Previously, usingifMatchwithout explicitly settingallowOverwrite: truewould cause the server to send conflicting conditional headers to S3, resulting in 500 errors. Now the SDK implicitly enablesallowOverwritewhenifMatchis set, and throws a clear error ifallowOverwrite: falseis explicitly combined withifMatch.
- c9d9a1a: Apply
- 2.3.14 Mar 2026
Release notes
Open source →Patch Changes
- a9a733a: fix: validate URL domain in
get()to prevent sending the token to arbitrary hosts
- a9a733a: fix: validate URL domain in
- 2.3.019 Feb 2026
Release notes
Open source →Minor Changes
-
04ca1f0: Add private storage support (beta), a new
get()method, and conditional getsPrivate storage (beta)
You can now upload and read private blobs by setting
access: 'private'onput()andget(). Private blobs require authentication to access — they are not publicly accessible via their URL.New
get()methodFetch blob content by URL or pathname. Returns a
ReadableStreamalong with blob metadata (url, pathname, contentType, size, etag, etc.).Conditional gets with
ifNoneMatchPass an
ifNoneMatchoption toget()with a previously received ETag. When the blob hasn't changed, the response returnsstatusCode: 304withstream: null, avoiding unnecessary re-downloads.Example
import { put, get } from "@vercel/blob"; // Upload a private blob const blob = await put("user123/avatar.png", file, { access: "private" }); // Read it back const response = await get(blob.pathname, { access: "private" }); // response.stream — ReadableStream of the blob content // response.blob — metadata (url, pathname, contentType, size, etag, ...) // Conditional get — skip download if unchanged const cached = await get(blob.pathname, { access: "private", ifNoneMatch: response.blob.etag, }); if (cached.statusCode === 304) { // Blob hasn't changed, reuse previous data }Learn more: https://vercel.com/docs/vercel-blob/private-storage
-
- 2.3.0-cc8f7be-2026021714025517 Feb 2026pre-release
Nothing published for this version
- 2.3.0-9e312ca-2026021713194717 Feb 2026pre-release
Nothing published for this version
- 2.3.0-512846a-202602062317096 Feb 2026pre-release
Nothing published for this version
- 2.3.0-45afd02-2026021710124017 Feb 2026pre-release
Nothing published for this version
- 2.2.06 Feb 2026
Release notes
Open source →Minor Changes
- 2b1cbbc: Add
ifMatchoption todel()for conditional deletes (optimistic concurrency control). Only works for single-URL deletes.
- 2b1cbbc: Add
- 2.2.0-f6bb7b4-202602041653254 Feb 2026pre-release
Nothing published for this version
- 2.1.04 Feb 2026
Release notes
Open source →Minor Changes
-
6c68442: Add ETag support for conditional writes (optimistic concurrency control)
- Return
etagin all blob responses (put, copy, head, list, multipart) - Accept
ifMatchoption in put/copy/createMultipartUpload for conditional writes - Add
BlobPreconditionFailedErrorfor ETag mismatch (HTTP 412)
Usage Example: Preventing Lost Updates
When multiple users or processes might update the same blob concurrently, use
ifMatchto ensure you don't overwrite someone else's changes:import { put, head, BlobPreconditionFailedError } from "@vercel/blob"; // User 1: Read the current blob and get its ETag const metadata = await head("config.json"); console.log(metadata.etag); // e.g., '"abc123"' // User 2: Also reads the same blob (same ETag) const metadata2 = await head("config.json"); // User 1: Updates the blob with ifMatch // This succeeds because the ETag matches const result1 = await put( "config.json", JSON.stringify({ setting: "user1" }), { access: "public", allowOverwrite: true, // Required when updating existing blobs ifMatch: metadata.etag, // Only write if ETag still matches } ); console.log(result1.etag); // New ETag: '"def456"' // User 2: Tries to update with their (now stale) ETag // This fails because User 1 already changed the blob try { await put("config.json", JSON.stringify({ setting: "user2" }), { access: "public", allowOverwrite: true, ifMatch: metadata2.etag, // Stale ETag - blob was modified! }); } catch (error) { if (error instanceof BlobPreconditionFailedError) { // The blob was modified since we last read it // Re-fetch, merge changes, and retry const freshMetadata = await head("config.json"); await put("config.json", JSON.stringify({ setting: "user2" }), { access: "public", allowOverwrite: true, ifMatch: freshMetadata.etag, // Use fresh ETag }); } }Key Points
allowOverwrite: true: Required when updating an existing blob at the same pathifMatch: Only performs the write if the blob's current ETag matches this value- Combined: "Overwrite, but only if the blob hasn't changed since I last read it"
- ETags follow RFC 7232 format with surrounding quotes (e.g.,
"abc123")
- Return
-
- 2.1.0-f8529bc-2026012922415429 Jan 2026pre-release
Nothing published for this version
- 2.1.0-f0898fb-2026012712532327 Jan 2026pre-release
Nothing published for this version
- 2.1.0-73e660a-202602021641382 Feb 2026pre-release
Nothing published for this version
- 2.1.0-704ff70-2026012615021826 Jan 2026pre-release
Nothing published for this version
- 2.1.0-704ff70-2026012318015623 Jan 2026pre-release
Nothing published for this version
- 2.1.0-4adc7b7-2026012916590029 Jan 2026pre-release
Nothing published for this version
- 2.1.0-454414f-202602041618134 Feb 2026pre-release
Nothing published for this version
- 2.1.0-39df1d8-2026012116111921 Jan 2026pre-release
Nothing published for this version
- 2.1.0-371428d-2026011915222019 Jan 2026pre-release
Nothing published for this version
- 2.1.0-06d6754-2026012218314422 Jan 2026pre-release
Nothing published for this version
- 2.1.0-062a059-2026012814105728 Jan 2026pre-release
Nothing published for this version
- 2.0.123 Jan 2026
- 2.0.016 Sept 2025
Release notes
Open source →Major Changes
-
0b8ead9: BREAKING CHANGE:
To continue receiving
onUploadCompletedcallback once a file is uploaded with Client Uploads when not hosted on Vercel, you need to provide thecallbackUrlat theonBeforeGenerateTokenstep when usinghandleUpload.When hosted on Vercel: No code changes required. The
callbackUrlis inferred from Vercel system environment variables:- In preview environment:
VERCEL_BRANCH_URLwhen available, otherwiseVERCEL_URL - In production environment:
VERCEL_PROJECT_PRODUCTION_URL
If you're not hosted on Vercel or you're not using Vercel system environment variables, your will need to provide the
callbackUrl:Before:
await handleUpload({ body, request, onBeforeGenerateToken: async (pathname) => { /* options */ }, onUploadCompleted: async ({ blob, tokenPayload }) => { /* code */ }, });After:
await handleUpload({ body, request, onBeforeGenerateToken: async (pathname) => { return { callbackUrl: 'https://example.com' }; // the path to call will be automatically computed }, onUploadCompleted: async ({ blob, tokenPayload }) => { /* code */ }, });For local development: Set the
VERCEL_BLOB_CALLBACK_URLenvironment variable to your tunnel URL:VERCEL_BLOB_CALLBACK_URL=https://abc123.ngrok-free.appSee the updated documentation at https://vercel.com/docs/vercel-blob/client-upload to know more.
Details:
Before this commit, during Client Uploads, we would infer the
callbackUrlat the client side level (browser) based onlocation.href(for convenience). This is wrong and allows browsers to redirect the onUploadCompleted callback to a different website.While not a security risk, because the blob urls are already public and the browser knows them, it still pose a risk of database drift if you're relying on onUploadCompleted callback to update any system on your side.
- In preview environment:
Additional notes
Open source →Major Changes
-
d02e08a: Enable auto pipelining by default. We're making this a major release for safety, but we believe most applications can upgrade from 1.x to 2.x without any changes. Auto pipelining should work by default and improve performance.
BREAKING CHANGE: Auto pipelining is on by default now. See https://upstash.com/docs/oss/sdks/ts/redis/pipelining/auto-pipeline. This brings performance benefits to any code making multiple redis commands simultaneously.
If you detect bugs because of this, please open them at https://github.com/vercel/storage/issues.
You can disable this new behavior with:
import { createClient } from '@vercel/kv'; const kv = createClient({ url: .., token: .., enableAutoPipelining: false });
-
- 2.0.0-831c3252-2025091207321712 Sept 2025pre-release
Nothing published for this version