Blazer

Blazer is a Go client library for Backblaze B2 Cloud Storage,
maintained by Backblaze.
import "github.com/Backblaze/blazer/b2"
Blazer targets the B2 Native API. Unless you specifically need the Native API, you should use the
MinIO Go Client SDK with B2's
S3 Compatible API.
Many thanks to Toby Burress (kurin) for creating and maintaining Blazer for its
first six years.
Contents
Features
- Streaming I/O.
Writer and Reader implement io.Writer and io.Reader; large files are split
into parts automatically, with concurrent part uploads and ranged, concurrent downloads.
- Large files. Resumable uploads, server-side copies, and
Bucket.Compose to build a file from
uploaded and copied parts.
- Encryption. Per-request SSE-B2 and SSE-C (customer-supplied keys) for uploads, downloads, metadata
lookups and copies.
- Object Lock. File retention and legal hold on upload.
- Buckets and keys. Create, update and delete buckets; create and list application keys; issue
download authorization tokens for a prefix.
- Replication and notifications.
SetupReplication and ReplicationStatus; event-notification rules,
plus VerifySignature and ParseEvent for inbound webhooks.
- Sync.
b2/sync pushes a local directory tree into a B2 prefix, with dry runs and per-file results.
- Progress and status. Byte-level progress callbacks for uploads and downloads, and a
Client.Status
snapshot you can serve over HTTP.
- Reliable by default. Retries with backoff,
Retry-After support and automatic reauthorization;
optional session persistence with WithAccountInfo.
- No third-party dependencies. The
b2 package imports only the Go standard library.
Install
go get github.com/Backblaze/blazer/b2
Blazer supports the Go version in go.mod and newer; CI tests the Go 1.26.10 minimum on
Ubuntu and Go 1.27.3 plus the current stable release on Ubuntu, macOS, and Windows. Releases follow
semantic versioning and are listed in the
changelog.
You need a B2 application key. Give it
only the capabilities and buckets your program uses.
Packages
| Package |
Purpose |
b2 |
The client library. Start here. |
b2/sync |
Sync a local directory tree into a B2 prefix. |
base |
A thin, low-level mapping of the B2 Native API calls that b2 is built on. |
x/... |
Experimental packages; their API may change between minor releases. |
bin/b2keys |
A small command-line tool for creating application keys (a separate module). |
Examples
Getting started
import "os"
id := os.Getenv("B2_APPLICATION_KEY_ID")
key := os.Getenv("B2_APPLICATION_KEY")
ctx := context.Background()
// b2_authorize_account
b2, err := b2.NewClient(ctx, id, key)
if err != nil {
log.Fatalln(err)
}
buckets, err := b2.ListBuckets(ctx)
if err != nil {
log.Fatalln(err)
}
Copy a file into B2
func copyFile(ctx context.Context, bucket *b2.Bucket, src, dst string) error {
f, err := os.Open(src)
if err != nil {
return err
}
defer f.Close()
obj := bucket.Object(dst)
w := obj.NewWriter(ctx)
if _, err := io.Copy(w, f); err != nil {
w.Close()
return err
}
return w.Close()
}
If the file is no larger than the writer's ChunkSize (100 MB by default), Blazer buffers it and sends
it with b2_upload_file. Larger files are uploaded in ChunkSize parts with B2's large file API, which
always produces at least two parts.
Copy a file into B2, with multiple concurrent uploads
Uploading a large file with multiple HTTP connections is simple:
func copyFile(ctx context.Context, bucket *b2.Bucket, writers int, src, dst string) error {
f, err := os.Open(src)
if err != nil {
return err
}
defer f.Close()
w := bucket.Object(dst).NewWriter(ctx)
w.ConcurrentUploads = writers
if _, err := io.Copy(w, f); err != nil {
w.Close()
return err
}
return w.Close()
}
This uploads up to writers parts at a time. ChunkSize sets the part size: 100 MB by default, at least
5 MB, at most 5 GB.
Download a file from B2
Downloading is as simple as uploading:
func downloadFile(ctx context.Context, bucket *b2.Bucket, downloads int, src, dst string) error {
r := bucket.Object(src).NewReader(ctx)
defer r.Close()
f, err := os.Create(dst)
if err != nil {
return err
}
r.ConcurrentDownloads = downloads
if _, err := io.Copy(f, r); err != nil {
f.Close()
return err
}
return f.Close()
}
List all objects in a bucket
func printObjects(ctx context.Context, bucket *b2.Bucket) error {
iterator := bucket.List(ctx)
for iterator.Next() {
fmt.Println(iterator.Object())
}
return iterator.Err()
}
Report upload progress
w := bucket.Object(dst).NewWriter(ctx, b2.WithProgress(func(done, total int64) {
log.Printf("%d of %d bytes", done, total)
}))
Encrypt with a customer-supplied key (SSE-C)
key, err := b2.NewSSECKey(secret) // 32 bytes; keep it safe, B2 does not store it
if err != nil {
return err
}
w := bucket.Object("private.bin").NewWriter(ctx, b2.WithSSECKey(key))
// ... write and close w, then read it back with the same key:
r := bucket.Object("private.bin").NewReader(ctx, key)
Use b2.WithSSEB2("AES256") instead for B2-managed encryption on a single upload.
Sync a local directory
import "github.com/Backblaze/blazer/b2/sync"
res, err := sync.Sync(ctx, bucket, "backups/", "./data", sync.WithConcurrency(4))
if err != nil {
return err
}
log.Printf("uploaded %d, skipped %d, failed %d", len(res.Uploaded), len(res.Skipped), len(res.Failed))
Add sync.WithDryRun() to see what would be uploaded without writing anything.
Grant temporary auth to a file
Say you have a number of files in a private bucket, and you want to allow other
people to download some files. This is possible to do by issuing a temporary
authorization token for the prefix of the files you want to share.
token, err := bucket.AuthToken(ctx, "photos", time.Hour)
If successful, token is then an authorization token valid for one hour, which
can be set in HTTP GET requests.
The hostname to use when downloading files via HTTP is account-specific and can
be found via the BaseURL method:
base := bucket.BaseURL()
More runnable code lives in examples/, and every exported identifier is documented on
pkg.go.dev.
Testing resilience with B2 test mode
B2 provides documented "test mode" hooks (sent as the X-Bz-Test-Mode request
header) that ask the service to inject controlled failures, so you can exercise
your retry and error-handling paths without waiting for real faults. blazer
exposes each one as a client option:
// Ask B2 to fail some uploads so you can verify your upload retries.
client, err := b2.NewClient(ctx, id, key, b2.FailSomeUploads())
| Option |
X-Bz-Test-Mode value |
Effect |
b2.FailSomeUploads() |
fail_some_uploads |
B2 fails some uploads, exercising upload retries. |
b2.ExpireSomeAuthTokens() |
expire_some_account_authorization_tokens |
B2 expires account authorization tokens frequently, exercising re-authentication. |
b2.ForceCapExceeded() |
force_cap_exceeded |
B2 behaves as if the account storage cap were exceeded. Backblaze documents it for upload- and download-related calls. |
Backblaze documents each value on its own and does not say whether several can be
combined. Enabling more than one option sends one X-Bz-Test-Mode header line per
option. blazer's live integration tests combine b2.FailSomeUploads() and
b2.ExpireSomeAuthTokens(), but that does not establish that every combination is
supported by the B2 service, so prefer one option per client unless you have
verified the combination you need.
The header is set when the client is created and sent with every request that
client makes, including authorization and downloads. There is no way to turn it
off afterwards, so create a separate client for tests and leave these options off
in production. See Backblaze's
Integration Checklist
for the authoritative behavior.
Contributing
Issues and pull requests are welcome. Read CONTRIBUTING.md before opening a PR: it covers
make ci (the same checks CI runs), changelog entries with changie, and the review
process in REVIEW.md. Contributor references, including the B2 behaviors Blazer must get right,
are in docs/. Coding agents start from AGENTS.md. Releases follow
RELEASE.md.
Please follow the Code of Conduct.
Contributors
Thanks to everyone who has contributed to Blazer.

Security
Do not open public issues for vulnerabilities. See SECURITY.md for how to report one.
Licenses
Blazer is licensed under the Apache License 2.0.
The b2 package does not consume any third-party packages; it depends only on the Go standard library and
code within the blazer repository. A report of used licenses is in b2/licenses.csv,
generated with go-licenses. Double-check it yourself if this is a
concern: it can become stale as the code changes.
Backblaze ecosystem