A Bitcoin node doesn't come with a graphical interface, no app-style visuals, no clickable "Send" button. And yet block explorers, wallet apps, payment providers, and countless custom tools are all built on top of exactly this node. The reason: a standardized interface that lets practically any software talk to a running Bitcoin node.
Why a Dedicated Interface Is Even Necessary
You might wonder why a Bitcoin node isn't simply embedded directly as a program library into other software, instead of communicating via the detour of its own network interface. The reason lies in the separation of responsibilities: the node itself (written in C++, see Part 1 of this series) runs as a standalone, permanently active background process, regardless of which programming language the requesting application is written in. A wallet app on your phone, a web backend in Python or JavaScript, a command-line script in Bash, all of them can talk to the same node in exactly the same way, without the node itself ever having to know who's asking or in what language that application was written. This clean separation is a major reason such a diverse ecosystem of applications was able to grow up around Bitcoin Core, without every single one of them needing to bring its own elaborate Bitcoin implementation.
JSON-RPC: A Simple Question-and-Answer Language
Bitcoin Core exposes its functionality through a so-called JSON-RPC interface: a widely used, simple format where a requesting application sends a clearly named command with a few parameters and gets back a structured response. bitcoin-cli, the bundled command-line tool, is itself fundamentally just a very thin translator that packages your input into exactly such a request.
bitcoin-cli: The Simplest Door Into All of It
For most node operators, bitcoin-cli is the first, and often only, direct contact with this interface. It's a deliberately lean command-line program that essentially does just three things: package your typed-in parameters into a valid JSON-RPC request, send that request to the locally running node, and print the returned, usually also JSON-formatted response readably to the screen. It contains no Bitcoin logic of its own; no matter how complicated the question you ask with it, the node actually answers it, not the command-line program itself. This radical simplicity is intentional: it keeps the attack surface small and makes the tool's own code easy to audit, a reassuring thought for a program that potentially accepts commands to send money.
Organized by Topic
In the source code, the available commands are cleanly split by topic area into their own files (src/rpc/blockchain.cpp, src/rpc/rawtransaction.cpp, src/rpc/net.cpp, src/rpc/mining.cpp, plus a dedicated module for wallet commands) and registered there in command tables. A small excerpt from the "blockchain" category shows the pattern:
{"blockchain", &getblockchaininfo},
{"blockchain", &getbestblockhash},
{"blockchain", &getblock},
{"blockchain", &gettxout},
{"blockchain", &gettxoutsetinfo},
A handful of core commands are enough for a first sense of it: getblockchaininfo returns the current status of the blockchain (height, difficulty, sync progress), getblock and getblockheader return the raw data of a specific block, gettxout checks a single, still-unspent output amount, sendrawtransaction feeds a fully signed transaction into the network, and getrawmempool shows the current waiting room (see Part 4). Wallet-specific commands like listunspent or sendtoaddress are only available if a wallet is actually enabled in the node.
An Example: How a Block Explorer Works Behind the Scenes
To make this concrete, it's worth looking at what happens when you type a transaction ID into any block explorer website and see all the details within a fraction of a second. Behind the scenes, there's usually a full Bitcoin node running, typically with the transaction index enabled (more on that in the final part of this series). The website itself contains no blockchain logic of its own; it simply translates your input into an RPC call like getrawtransaction, formats the returned, fairly technical, cryptic raw data (hex-encoded values, timestamps as plain numbers) into something human-readable, and displays it to you nicely formatted. A complete "block explorer" is, at its core, nothing more than a very well-made presentation layer on top of exactly the interface described in this post; anyone could build their own private block explorer with a few lines of code, without having to trust any third-party servers at all.
Push Instead of Pull: The ZMQ Interface
RPC calls have a small structural downside: they work on an "ask, then get an answer" basis, an application that wants to be notified the instant a new block arrives would otherwise have to keep asking repeatedly ("is there a new block yet? and now? and now?"). For this, Bitcoin Core additionally offers a second, complementary interface, based on the widely used ZeroMQ messaging technology (src/zmq/). A node can use this to proactively send out notifications, with no prior request at all, whenever certain events occur, defined in the code as dedicated topic channels: hashblock and rawblock for new blocks, hashtx and rawtx for new transactions, and sequence for all mempool changes. Applications that depend on up-to-the-second data (say, payment providers that need to know immediately when an expected payment arrives) simply subscribe to the relevant channel, instead of bombarding the node with constant requests.
A Third Door: The Simple REST Interface
Alongside JSON-RPC and the ZMQ notifications just described, Bitcoin Core also offers a third, deliberately simple access method: a classic REST interface (src/rest.cpp), the kind countless ordinary websites use for simple data queries too. Instead of a structured RPC call, a perfectly ordinary web address is enough here to retrieve information: for example /rest/tx/ for a single transaction, /rest/block/ for a complete block, /rest/chaininfo for the current chain status, /rest/mempool/ for the current mempool contents (see Part 4), or /rest/getutxos for a targeted query of the UTXO set. The big advantage: these endpoints can be called up quite literally with an ordinary web browser or a simple command-line tool, without an application needing to understand the more structured JSON-RPC format at all, ideal for quick, one-off lookups or very simple integrations where the effort of a full RPC connection isn't worth it.
Deliberately Not Wide Open
Because RPC access, with a wallet enabled, can in the worst case grant full access to your bitcoin balance (including the command to send it), access is strictly locked down by default: reachable only from the machine itself (localhost), and only with valid authentication, either via an automatically generated cookie file or a self-configured password. Anyone who wants to open this interface beyond their own network (say, to access it from another machine on their home network) should only do so over an encrypted, additionally secured channel (e.g. a VPN or an SSH tunnel), and should be aware of the stakes: an open, insufficiently protected RPC port on the open internet is a digital master key to your own node, and is actively hunted for by automated scanners in practice.
Multiple Questions at Once: Batch Requests
Anyone who needs to query a lot of individual pieces of information (say, a payment provider checking the status of a hundred different, currently expected payments at once) would face a huge number of individual network round trips between application and node if limited to one request per question. The JSON-RPC format used by Bitcoin Core therefore allows so-called batch requests: several individual commands are sent together in a single request, the node processes them internally one after another, and sends back all the answers bundled into a single response. This considerably reduces network overhead, and is one of the reasons even data-intensive applications like large block explorer platforms (see above) can be run with comparatively manageable technical effort.
A Call to Try It Yourself
To make this a bit more tangible: anyone running their own Bitcoin node can type directly into the command line:
bitcoin-cli getblockchaininfo
The answer comes back as a structured data set that includes, among other things, the name of the chain (main for the real network), the current block height, the hash of the latest block, and the current difficulty, exactly the same values every wallet app and every block explorer queries behind the scenes, just raw and unformatted. This one command is often the first direct contact technically curious users have with their own node, and at the same time the simplest way to prove to yourself that your own node is genuinely running and synced, rather than just taking an app's word for it.
Conclusion: The Unassuming Foundation Behind Almost Everything You See as a User
Whether it's a block explorer website, a mobile wallet app, or a company's payment backend: almost everywhere software interacts with the Bitcoin network, there's ultimately a call to exactly this JSON-RPC interface behind it, usually hidden so well that few users ever find out.
Next up, Part 8: The Blockchain's Memory, how nodes keep additional records to answer certain questions instantly.