The B2 command line tool and how ApiVer keeps scripts from breaking
The command-line tool that gives easy access to all of the capabilities of B2 Cloud Storage
At a glance
- What is it?
- Backblaze's b2 command line tool is a Python client for B2 Cloud Storage, and the interesting part is not the file commands but the ApiVer scheme, which ships parallel b2v3, b2v4 and b2v5 entry points so a long running script keeps the interface it was written against.
- Who is it for?
- The b2 tool fits a backup script or a pipeline that needs to reach B2 Cloud Storage from a shell, and the b2v5 command fits one that has to keep running across upgrades.
- Can I use it commercially?
- Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
- Is it still maintained?
- Yes. The repository received new commits within the last day.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Four install routes, and one of them is discouraged
The b2 tool gives command line access to the B2 service, and the README opens with five ways to install it, which is unusual for a project of this size to state so plainly.
The first is Homebrew, recommended as the quickest setup for Mac users, with the B2 CLI Homebrew formula:
brew install b2-toolsThe second is stand-alone binaries for Linux and Windows, described as the most straightforward way to use the tool and sufficient in most use cases, with the latest versions on the Releases page.
The third is the Python Package Index, where a virtualenv is recommended:
pip install b2[full]The extra is not required. The README says the extra dependencies improve the debugging experience and, potentially, the performance of the b2 CLI, but are not strictly required, and you can install without them:
pip install b2The fourth is the source install, and here the README is unusually direct about it. Installing from source is not recommended, unless you want to check if a current pre-release code solves a bug affecting you.
That ordering tells you something about how the project thinks about its users. The pip package is the primary route for Python environments, the binaries and the container cover everyone else, and the source tree is a debugging aid rather than a supported deployment path. The Docker image is described as the truly platform independent solution, and the image is referenced as backblazeit/b2:latest.
The manifest shows the floor: Python 3.10 or newer, with classifiers for 3.10 through 3.14, and the core dependency set is small, with b2sdk as the piece that does the actual work and argcomplete, arrow, tabulate and tqdm around it.
The subcommand list shows what the tool is actually for
The usage section prints the top level commands, and the list is worth reading as a description of the tool's scope.
b2 account Account management subcommands.
b2 bucket Bucket management subcommands.
b2 file File management subcommands.
b2 install-autocomplete Install autocomplete for supported shells.
b2 key Application keys management subcommands.
b2 license Print the license information for this tool.
b2 ls List files in a given folder.
b2 replication Replication rule management subcommands.
b2 rm Remove a "folder" or a set of files matching a pattern.
b2 sync Copy multiple files from source to destination.
b2 version Print the version number of this tool.Two of these deserve comment. install-autocomplete is a first class command rather than a note in the docs, which is a small signal about how the project expects the tool to be used day to day. And license prints the licence information for the tool itself, which is a useful habit for a tool whose output may end up in an audit.
The shape is that of a full administrative client. Account and key management are there, so the tool can create and revoke the credentials it uses. Bucket management covers the container layer. File management and ls handle objects, rm removes a folder or a set of files matching a pattern, and sync copies multiple files from source to destination. Replication rule management is also present, which is the one command here that touches the service's own features rather than the object store.
For a finer level of detail, the README says to use b2 <command> --help for more details on a specific command, and the same note is repeated for capabilities, which we will come to.
Application keys need listBuckets before anything else works
There is a requirement that catches people out, and the README states it in a paragraph that is easy to skim past.
When authorizing with application keys, the tool requires that the key have the listBuckets capability, so that it can take the bucket names you provide on the command line and translate them into bucket IDs for the B2 Storage service.
The reason is a usability decision rather than a technical one. The command line is written in bucket names, because that is what a person remembers, and the tool does the lookup so you do not have to carry IDs around. The cost is that the credential you give the tool has to be allowed to list every bucket in the account, even if you only intend to touch one of them. Each different command may require additional capabilities, and the details for each command are in the help for that command.
So a least privilege credential and a convenient command line are in tension here, and the tool resolves the tension in favour of the command line. For a production account where the key is scoped narrowly, the practical answer is to accept the lookup cost and give the key the capability the tool asks for, or to use IDs directly if your workflow allows it.
The other piece of state worth knowing about is the authentication cache. The environment variable B2_ACCOUNT_INFO specifies the SQLite file used for caching authentication information, and you run b2 account get to see which file is currently in use, with its location depending on your profile and environment, and the resolution rules described in b2 --help.
ApiVer is the whole reason to use b2v5 in a script
This is the part of the project that has a real engineering idea in it, and it deserves more attention than most command line tools get.
The Docker image section refers to the ApiVer methodology, and the section on it explains the design. The summary has two bullets. In a terminal, for the best user experience, use the latest apiver interface provided by the b2 command. For long-term support, for example in scripts, use the b2v5 command.
The explanation is the interesting part. The ApiVer methodology exists so the team can continue to evolve the b2 command while still providing all the bugfixes to the old interface versions. If you use the b2 command you are working with the latest stable interface, with all the bells and whistles, the latest features and the best performance. But when writing a reliable, long-running script, you want to be sure the script will not break when a new version of the b2 command is released.
So instead you use a version-bound interface, b2v5. That command will always provide the same ApiVer 5 interface, regardless of the semantic version of the b2 command. Even if the b2 command goes into the ApiVer 6, 8 or even 10 with some major changes, b2v5 will still provide the same interface, the same commands and the same parameters, with all the security and bug fixes. The README is honest about the cost: over time it might get slower, as the tool may need to emulate some older behaviours, but it will not break.
That is a rare thing to find in a command line tool. Most tools either freeze their interface and ship no new features, or ship new features and break your scripts. This one does both, at the price of a few binary aliases and some emulation work.
The recent release history shows the scheme in action. v4.7.1 on 2026-06-08 was followed by v4.8.0 on 2026-09-15 and then v5.0.0 the same day, six minutes apart. A major semantic version and a minor one shipped together, which is exactly what you would expect when a new ApiVer interface is introduced alongside the old ones.
Running the container means deciding where the credentials live
The Docker section documents two authorisation patterns, and the difference between them matters for a scheduled job.
The first authorises on each command, passing the key and the key id as environment variables to the container:
B2_APPLICATION_KEY=<key> B2_APPLICATION_KEY_ID=<key-id> docker run --rm -e B2_APPLICATION_KEY -e B2_APPLICATION_KEY_ID backblazeit/b2:latest b2v5 bucket listThe second authorises once and persists the credentials:
docker run --rm -it -v b2:/root backblazeit/b2:latest b2v5 account authorize
docker run --rm -v b2:/root backblazeit/b2:latest b2v5 bucket list # remember to include `-v` - authorization details are thereThe comment in the second line is the operational warning. Without the volume mount, the authorised session is not there on the next run, and the failure looks like a credentials problem rather than a missing mount.
File transfer has the same two options. A single file can be piped in:
cat source_file.txt | docker run -i --rm -v b2:/root backblazeit/b2:latest b2v5 upload-unbound-stream bucket_name - target_file_nameor local paths can be mounted into the container:
docker run --rm -v b2:/root -v /home/user/path/to/data:/data backblazeit/b2:latest b2v5 file upload bucket_name /data/source_file.txt target_file_nameNote the volume name is b2 in all of these, and it is the same volume that holds the authorised session. One named volume therefore carries both the credentials and, if you mount it, your working data, which is convenient and is also a single thing to get right.
Where the b2 tool is the wrong choice
The first wrong case is expecting a full featured synchronisation client. The b2 tool has sync for copying multiple files from source to destination and rm for removing a folder or a set of files matching a pattern, and that is a command line client with a service behind it, not a backup product with conflict resolution, version history and a scheduler. If your requirement is a reliable nightly backup with retention and restore, you are looking at a product rather than a tool, and the b2 tool is a building block inside one.
The second wrong case is an environment where you cannot install a Python package or run a container. The standalone binaries for Linux and Windows cover that, so the tool is not out of reach, but if your constraint is that nothing may be installed at all, then a direct API client written against the service, using the b2sdk library that this tool itself depends on, is the more honest path.
The third wrong case is a team that has already standardised on a different object storage CLI and wants one set of habits. The b2 tool is specific to B2 Cloud Storage, and while the object model is familiar, the flags, the key management commands and the bucket naming are not the same as the other tools in that category.
The alternative worth naming is the service's own SDK, b2sdk, which is the library underneath this command line tool. The difference in approach is that the SDK gives you the full API surface and no command line conventions, and you write the plumbing, while the tool gives you a documented set of subcommands, a cache of your authorised session, shell completion and the ApiVer safety net for scripts. For an operator who wants to run commands and read the output, the tool is the better fit. For a service that needs to talk to B2 from application code, b2sdk is the better fit, and using the tool inside an application would be a strange choice. There is also the third option of the service's own integrations in other tooling, which is worth checking before you adopt either, because the point of a command line client is to avoid writing glue.
Licence, maintenance and what the repository shows about the release process
The project metadata records the licence as one GitHub cannot classify, which means the terms live in the LICENSE file at the repository root rather than in a standard identifier. The project manifest is more direct about it, with license = {text = "MIT"} in pyproject.toml and an MIT classifier. So the source is MIT, and if you need the exact wording for a compliance file, the LICENSE file is where to read it.
The repository is not archived and the last push was on 2026-10-19, so the work is current, with v5.0.0 released on 2026-09-15 and v4.8.0 the same day.
The release plumbing is visible in the file list, and it is more sophisticated than most projects of this size. There is a changelog.d directory and a towncrier dependency pinned in the release dependency group, which is the standard pattern of collecting fragment files per change and assembling a changelog at release time. There is a README.release.md, a b2.spec.template for building RPM packages, a pyinstaller-hooks directory for the standalone binaries, a docker directory, a noxfile.py, and a uv.lock. The license dependency group is interesting on its own, with pip, pip-licenses, pipdeptree and prettytable, and the lint group includes liccheck with a note that setuptools is required by it, which suggests the project checks its own dependency licences automatically.
That last point is a good signal for a tool from a storage vendor, whose users are often enterprises with a supply chain review process. The tooling is set up to answer those questions in CI rather than in a spreadsheet.
Editorial conclusion
The b2 tool fits a backup script or a pipeline that needs to reach B2 Cloud Storage from a shell, and the b2v5 command fits one that has to keep running across upgrades. It is the wrong choice if you want a full featured sync with conflict handling and version history, since the tool is a client first and the storage service itself is the other half, and it is the wrong choice if your environment cannot install a Python package, since the standalone binaries and the Docker image are the alternative and both need their own attention. Before you adopt it, decide whether your scripts will use the b2 command or a version-bound one, and read the ApiVer section of the README, because that choice is what determines whether an upgrade breaks your automation.
Frequently asked questions
How do I install the Backblaze b2 command line tool?
With brew install b2-tools on Mac, from the standalone Linux and Windows binaries on the Releases page, with pip install b2[full] from PyPI, or with docker run backblazeit/b2:latest. Installing from source with pip install git+https://github.com/Backblaze/B2_Command_Line_Tool.git is described as not recommended except for checking a pre-release fix.
What is the ApiVer methodology in the b2 command line tool?
It is the scheme that lets the b2 command keep evolving while older interfaces keep working. The b2 command gives the latest stable interface for interactive use, while a version-bound command such as b2v5 always provides the same interface regardless of the b2 command's version, so long running scripts do not break.
Why does the b2 tool need the listBuckets capability?
Because it translates the bucket names you give on the command line into bucket IDs for the B2 Storage service. The README says each different command may require additional capabilities, and the details for each command are in that command's help.
How do I keep b2 credentials between Docker runs?
Mount a volume at /root when you run b2v5 account authorize, and include the same mount on later runs, because the authorisation details are stored in that volume. The README's example uses a volume named b2 and notes to remember to include the -v flag on subsequent commands.
What licence is the b2 command line tool released under?
The project manifest records MIT, with a LICENSE file at the repository root holding the terms, and the repository's own metadata lists the licence as a custom one that GitHub cannot classify.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/backblaze-b2-command-line-tool)Was this useful?