Bruno vs Postman
Bruno is an open-source API Client that has been gaining traction, challenging the highly popular Postman. This project aims to grow with community support, without third-party company involvement (except as sponsors) and has a strong desire to remain independent. They intend to maintain their identity, accepting external help without allowing any interference in project management.
Why Choose Bruno
For many, Postman is synonymous with reliability and familiarity. Despite some minor limitations (like only being able to modify requests through its interface), it has always met my needs. My collections have been there for ages, and the thought of reorganizing them elsewhere always gave me chills.
Everything was perfect until I needed to share my requests seriously with the team for effective collaboration. With the subscription costs and the frequent changes required for shared management of calls, my doubts grew daily.
Then Bruno arrived (the name reminds me of a movie). Its simple architecture immediately caught my attention, prompting me to import some of my Postman collections.
In this post, I will summarize the points of contact (or friction) between the two competitors, analyzing them from both perspectives to declare the possible winner of this challenge. Let’s begin!
Configuration Storage
While Postman saves collection and request configurations in its cloud, Bruno stores them on the local machine’s filesystem in “bru” files. This may seem trivial, but it significantly impacts collaboration, usability, and privacy.
In terms of usability, besides Bruno’s UI, we can directly modify the configuration files (the “.bru” files), which are simple text files. A great editor for editing Bru files is Visual Studio Code, with a “Bruno” extension for syntax highlighting.
Bruno doesn’t have its own cloud (and according to their Manifest, likely never will), meaning the persistence of configurations is entirely user-managed. Therefore, with configuration files residing only on our machines, privacy is guaranteed. Sharing them is solely up to us.
Collaboration
Contrary to Postman, which stores our configurations in its cloud, Bruno’s request (and collection) definitions are local, represented by text files in Bru format. While in Postman, you can back up collections by exporting them; in Bruno, you can easily transform your filesystem structure into a Git (or SVN, or Mercurial) repository and push it to BitBucket, GitHub, or GitLab.
This implements team-level sharing! Postman requires purchasing licenses for teams larger than three users (with not-so-popular prices), while Bruno offers this capability for free, with no limits on what or with whom you share requests. Isn’t that wonderful?
Online vs Offline
I must admit, I never noticed this detail because I am always connected. However, it turns out Postman works only in online mode. It doesn’t start if it cannot contact its servers. Bruno, on the other hand, has no connection requirement since everything it needs resides on the local filesystem. This means you can make calls to your local environment even if you are isolated from the rest of the world.
Using External Libraries
Using external libraries is standard for a developer and makes sense in this context. Both Postman and Bruno offer preloaded libraries covering most needs, such as:
Postman | Library | Bruno |
---|---|---|
✓ | ajv | ✓ |
axios | ✓ | |
node-fetch | ✓ | |
✓ | atob | ✓ |
✓ | btoa | ✓ |
✓ | chai | ✓ |
✓ | lodash | ✓ |
✓ | moment | ✓ |
✓ | uuid | ✓ |
nanoid | ✓ | |
✓ | crypto-js | ✓ |
✓ | cheerio | |
✓ | csv-parse | |
✓ | tv4 | |
✓ | xml2js | |
✓ | postman-collection |
Postman isn’t designed to easily integrate external libraries into its ecosystem. The alternatives are either downloading the library via script from a CDN and evaluating the returned string or placing the library’s source code in a variable at the collection (or environment) level and invoking an anonymous function to access its methods. This process is somewhat complex.
In Bruno, things are much simpler: create a package.json file with the libraries you want to include and put it in your project’s root directory. Then, install the dependencies with npm install
. The libraries are now available for use throughout your collection.
Scripting
Both Bruno and Postman allow customizing calls at different events:
- Pre-Request
- Post-Response
These events can be personalized at the individual request level or at the collection level, impacting all underlying requests. Scripting is necessary for various reasons, from pre-filling request/collection variables to handling JWT for authentication.
In scripting, Bruno provides three key variables:
req
– Represents the request.res
– Represents the response.bru
– Provides methods to interact with Bruno and its ecosystem.
In the “Pre Request” section, you can force request characteristics, set collection or environment-level variables, or even set the request method or URL. Bruno allows hiding secret values in an .env
file saved in your working directory. This file should be excluded from source control via .gitignore
. For collaborators, create an .env.example
with fake values to guide them in creating their .env
files.
You can extract values from secrets, generate random data using external libraries, and set values returned from other services. For example, extract a secret value from the current environment file and place it in both a Header (X-Secret) and a variable.
You can also define variables without scripting by using the declarative UI. These defined variables can be used in the request body, leveraging Bruno’s templating syntax. After executing the request, verify parameters in the “Timeline” tab of the UI.
Declarative Asserts
This feature immediately caught my attention as it simplified implementing basic tests while allowing complex logic via scripting. After each request, you can set tests to verify correct functionality based on your assumptions.
While in Postman, you write code for tests, Bruno offers a declarative way to define these tests, lightening your workload for simpler, more straightforward tests.
For example, test a call to api.chucknorris.io
, which typically responds with a JSON like this:
- Ensure the
value
field is a string. - Ensure the
id
field matches a specific Regular Expression. - Verify the response status is 200 (OK).
- Ensure
updated_at
is a date/time.
In Postman, you’d write code for these tests, which can also be done in Bruno with some syntax differences. However, Bruno allows declaring these tests in the “Assert” panel of your request. This simplicity means I can check the updated_at
field validity using just a Regular Expression without using the moment library.
Behind the scenes, these asserts translate to a few lines in the Bru file.
Executing Collections
During feature development, testing specific APIs is normal. At the end of the work, you typically run most (or all) requests in a collection to ensure no regressions. Here, Postman shows one of its most hated limits: the maximum number of monthly collection runs, which are:
- 25 for Free/Basic plans
- 250 for Professional plan
- Unlimited for Enterprise plan
Bruno imposes no such limits, allowing unlimited runs. Simply select “Run” from the collection’s dropdown menu to see the call results. Alternatively, Bruno offers a CLI runner (bru
) installable via npm. Run it with npm install -g @usebruno/cli
. Then, navigate to your collection’s main directory and use commands like:
bru run
to execute all requests in the current collection.bru run request.bru
to execute a specific request.bru run <folder>
to execute all requests in a specific directory.
Licensing Models
Software licenses are often a sore point for companies, seen as a cost without tangible benefits except enriching the producer. Bruno’s “Golden Edition” offers additional features over the Community version, such as:
- Bru File Explorer for directly modifying a request’s Bru file rather than managing additional JS scripts.
- Visual Git for visually managing source control interactions.
- Developer Tools for managing JSON structures and JWTs.
For Bruno, “License” primarily means “development support”. Postman’s licensing complexity matches its extensive offering: four plans (Free, Basic, Professional, and Enterprise) with increasing monthly prices per user. The most critical limit in the Free version is a team size of up to three users. To add even one more member, you must upgrade to at least the Basic version, incurring a significant cost.
What’s Missing in Bruno?
While Bruno’s first commit was in December 2021, Postman has been around since 2012, giving it nine more years to evolve and improve, becoming the industry standard. Bruno still lacks many features to be on par with Postman, such as:
- Flows – Visual editor for API call flows.
- Postbot – AI for generating API calls, documentation, and tests.
- Mock Servers – Simulate APIs by returning predefined fake data.
Despite these gaps, Bruno effectively supports daily development work. Bruno’s community is growing, promising a bright future filled with new ideas, features, and fixes, benefiting the product.
Conclusions
I’ve never believed in “perfect” software. Instead, I firmly believe in what best suits our needs. Without claiming to have the ultimate truth or needing to sell anything to anyone (which, as a technician, I can’t do), I recommend giving Bruno a chance. I’m sure you’ll like it and maybe find it’s just what you need.
I’m genuinely curious to hear your feedback: have you tried it? Did it solve any problems for you? What do you think doesn’t work or needs improvement?