Bitcoin
Ready to call this in production?
Free tier covers personal projects. Pay-as-you-go scales without a card.
Bitcoin
Free tier covers personal projects. Pay-as-you-go scales without a card.
Unlike the EVM world with its ethers and viem, Bitcoin has no single dominant high-level JavaScript SDK — most apps talk to the Bitcoin Core JSON-RPC API directly over a plain HTTP client. The two common choices are axios and node-fetch (or the global fetch built into modern Node), and either is enough to read chain data or broadcast a transaction. Note that building and signing transactions is a separate concern handled client-side by a library such as bitcoinjs-lib; the RPC endpoint only relays the finished hex. The recommendation is to wrap https://bitcoin.therpc.io/YOUR_API_KEY (the key from your TheRPC dashboard) in one small rpc() helper and reuse it for every call.
Every request uses Bitcoin Core's legacy JSON-RPC 1.0 envelope: { jsonrpc: "1.0", id: "therpc", method, params }. The params value is always a positional array — arguments go in a fixed order and are never passed as named keys, so getting the order right matters on each method. Your TheRPC API key lives in the URL path (https://bitcoin.therpc.io/YOUR_API_KEY), which keeps the request body identical to a call against any Bitcoin node.
Install axios with npm install axios, then build a single rpc() helper that posts the 1.0 envelope to the BTC endpoint and returns data.result. The key detail: a failed Bitcoin RPC still comes back as an HTTP 200 — the failure lives in the response body's error field, not in the HTTP status — so the helper checks data.error and throws on it rather than relying on axios to reject. With that in place, reading the chain tip (getblockcount) or decoding a verbose transaction (getrawtransaction with the second arg true) is a one-liner.
If you'd rather not add a dependency, node-fetch — or the global fetch shipped with modern Node and every browser — calls the same endpoint with no extra SDK. The helper is identical in spirit: serialize the 1.0 envelope, POST it as JSON, and pull result/error off the parsed body. Here it estimates a fee rate with estimatesmartfee (BTC/kvB, which you convert to sat/vByte with * 1e5) and then broadcasts a fully signed, hex-encoded transaction via sendrawtransaction, which returns the txid the network accepted into its mempool.
In TypeScript, give the envelope a generic shape — RpcResponse<T> with result: T | null and a nullable error — and make rpc<T>() return Promise<T> so each call site names the result type it expects (rpc<number>('getblockcount')). Watch the units when you type results: most Bitcoin methods report amounts as floating-point BTC (e.g. a value of 0.5), while a few — notably getblockstats — report them as integer satoshis (1 BTC = 100,000,000 sat). Typing a satoshi field as a BTC float, or vice versa, silently corrupts any math you do on it, so model each method's units deliberately.
fetch globally.sendrawtransaction.