Logo
New RPC users get 35% off their first monthView the offer
RPC Assistant

Bittensor RPC Endpoints: Connecting to the OpenTensor Foundation Network

Summary

Bittensor is a decentralized machine learning network where miners serve models and validators score them, all coordinated on the Finney mainnet built by the OpenTensor Foundation. To read chain state, submit extrinsics, or track subnet activity, your application needs a reliable RPC endpoint that speaks Substrate JSON-RPC over HTTP and WebSocket. This page explains how to connect, what to check before you commit, and how to keep your integration stable as subnets and traffic grow.

Bittensor is a decentralized network for machine learning, coordinated by the OpenTensor Foundation and running on the Finney mainnet. Miners register models on subnets, validators score those models, and TAO flows between them according to the network's incentive mechanism. If you are building a dashboard, a subnet explorer, a validator tool, or a miner monitoring script, you need to read and write to that chain — which means you need an RPC endpoint.

This page focuses on the practical side: how to connect to Bittensor over JSON-RPC, what to check before you pick an endpoint, and how to keep your integration stable as subnets and traffic grow. It is written for developers who already understand the basics of Substrate-based chains and want a working connection plus a clear way to decide between public, shared, and dedicated infrastructure.

Which Bittensor endpoint fits your workload?

Before you copy an endpoint, match it to what your application actually does. Bittensor traffic is unusual because a lot of it is read-heavy polling of subnet state, metagraph data, and stake balances, often at high frequency.

WorkloadTypical callsWhat to prioritize
Subnet explorer or dashboardchain_getBlock, state_getStorage, metagraph readsConsistent throughput and stable latency under many concurrent reads
Miner or validator monitoringsystem_health, author_pendingExtrinsics, balance readsFrequent polling without hitting shared rate limits
Wallet or staking UIauthor_submitExtrinsic, system_dryRunReliable write path and predictable confirmation handling
Indexer or analytics pipelineHistorical block and event readsArchive access and the ability to backfill from genesis
Real-time alertingNew block and event subscriptionsWebSocket support with reconnect handling

If your workload is exploratory — a script that runs a few times a day — a public endpoint is usually enough to start. If you are running a dashboard with many users, a monitoring loop that polls every few seconds, or an indexer that needs historical state, a shared or dedicated endpoint will save you from the failure modes described later in this article.

OnFinality provides Bittensor (Finney) RPC over both HTTP and WebSocket, alongside a range of other supported RPC networks. You can compare plans on the RPC pricing page, or move to isolated resources with a dedicated node if you need predictable capacity.

Chain settings at a glance

Bittensor is a Substrate-based chain, so it uses the standard Substrate JSON-RPC interface rather than the Ethereum JSON-RPC method set. Keep these settings handy when configuring wallets, SDKs, and monitoring tools.

SettingValue
NetworkBittensor Finney Mainnet
Native currencyTAO (9 decimals)
TransportHTTP and WebSocket
RPC interfaceSubstrate JSON-RPC
Public HTTP endpointhttps://bittensor-finney.api.onfinality.io/public
Public WebSocket endpointwss://bittensor-finney.api.onfinality.io/public-ws

Because the native currency uses 9 decimals, remember to scale TAO amounts by 1e9 when you convert between planck-style integers and human-readable values. A common bug in Bittensor tooling is displaying raw balances without that scaling, which makes stake and emission numbers look wrong by nine orders of magnitude.

Making your first JSON-RPC calls

Substrate chains expose a small set of core methods that most tooling relies on. Start with a health check and a chain identity read to confirm your endpoint is live and pointed at the right network.

# Confirm the node is healthy and synced
curl -s https://bittensor-finney.api.onfinality.io/public \
  -H 'Content-Type: application/json' \
  -d '{"jsonrpc":"2.0","id":1,"method":"system_health","params":[]}'

# Read the chain name to verify you are on Finney mainnet
curl -s https://bittensor-finney.api.onfinality.io/public \
  -H 'Content-Type: application/json' \
  -d '{"jsonrpc":"2.0","id":1,"method":"system_chain","params":[]}'

A healthy response returns isSyncing: false and a peer count. If isSyncing is true, the node is still catching up and reads may be stale — do not treat its state as final.

For application code, the Polkadot.js API is the most common way to talk to Bittensor. It handles the metadata, type registry, and SCALE encoding for you, which matters because raw state_getStorage calls require you to know storage keys and types.

import { ApiPromise, WsProvider } from '@polkadot/api';

const provider = new WsProvider('wss://bittensor-finney.api.onfinality.io/public-ws');
const api = await ApiPromise.create({ provider });

const [chain, health] = await Promise.all([
  api.rpc.system.chain(),
  api.rpc.system.health(),
]);

console.log('Chain:', chain.toString());
console.log('Syncing:', health.isSyncing.toString());

// Read the current block number
const header = await api.rpc.chain.getHeader();
console.log('Latest block:', header.number.toNumber());

Once connected, you can query subnet and stake state through the runtime modules. The exact storage keys and call names depend on the current runtime, so always read them from the live metadata rather than hard-coding values from an old tutorial.

Reading subnet and metagraph data

Most Bittensor applications care about subnet-level data: which neurons are registered, what their incentive and emission values are, and how stake is distributed. This data lives in runtime storage and is best accessed through the API's typed queries rather than raw storage keys.

// Iterate registered neurons on a subnet (structure depends on runtime version)
const entries = await api.query.subtensorModule.neurons.entries(1);

for (const [key, value] of entries) {
  const uid = key.args[1].toString();
  console.log('UID:', uid, 'Incentive:', value.incentive.toString());
}

Two practical notes. First, metagraph reads can be large — iterating every neuron on a busy subnet returns a lot of data, so paginate or filter where the runtime allows it. Second, subnet identifiers and module names have changed across runtime upgrades. Pin your client library version and test after every network upgrade, because a renamed storage item will silently break a query that used to work.

WebSocket subscriptions for live data

If you are building anything that reacts to new blocks or events — an alerting bot, a live dashboard, a miner that watches for registration changes — polling over HTTP will not scale well. Use a WebSocket subscription instead.

const provider = new WsProvider('wss://bittensor-finney.api.onfinality.io/public-ws');
const api = await ApiPromise.create({ provider });

// React to every new block
const unsub = await api.rpc.chain.subscribeNewHeads((header) => {
  console.log('New block:', header.number.toNumber());
});

// React to specific events as they are included
const unsubEvents = await api.query.system.events((events) => {
  events.forEach(({ event }) => {
    if (api.events.subtensorModule?.RegistrationAllowed?.is(event)) {
      console.log('Registration event detected');
    }
  });
});

WebSocket connections drop. Networks blip, laptops sleep, and load balancers recycle connections. Always implement reconnect logic with backoff, and re-subscribe after reconnecting. A subscription that silently stops delivering blocks is worse than an error, because your application keeps running on stale data.

Common failure modes and how to debug them

Most Bittensor RPC problems fall into a handful of patterns. Here is how to recognize and fix them.

SymptomLikely causeWhat to do
isSyncing: true for a long timeNode is behind or catching upWait, or switch to a fully synced endpoint
Reads return stale block numbersEndpoint is lagging the chain headCompare block height across two endpoints
state_getStorage returns nullWrong storage key or renamed moduleRead keys from live metadata, not old docs
Balances look off by 1e9Missing decimal scaling for TAOScale raw values by 1e9 before display
WebSocket stops deliveringDropped connection, no reconnectAdd backoff reconnect and re-subscribe
Intermittent 429 responsesShared endpoint rate limitingReduce polling frequency or move to a dedicated endpoint
Extrinsic rejectedNonce or fee issueRe-read nonce, check balance, use system_dryRun

A quick diagnostic habit: when something looks wrong, query system_health and chain_getHeader on two different endpoints and compare. If the block heights differ, you have a sync or lag problem, not a bug in your code.

Evaluating a Bittensor RPC provider

Once you move past a quick prototype, the endpoint becomes part of your production surface. These are the criteria that actually matter for Bittensor workloads.

CriterionWhy it matters for Bittensor
HTTP and WebSocket supportSubstrate tooling uses both; polling-only endpoints limit real-time features
Archive accessIndexers and analytics need historical state, not just the chain head
Throughput under concurrent readsMetagraph and subnet queries are read-heavy and bursty
Rate limit transparencyYou need to know when you will be throttled before it happens
Runtime upgrade handlingBittensor upgrades change storage and modules; the provider must keep nodes current
Failover optionsA single endpoint is a single point of failure for your app
Support responsivenessSubstrate debugging benefits from a provider that understands the stack

OnFinality runs Bittensor (Finney) RPC as part of a broader network portfolio, so you can keep your Substrate and EVM integrations on consistent tooling. If you want to compare this against other chains and providers, the how to choose an RPC provider article walks through the general evaluation framework.

Build versus buy for Bittensor infrastructure

Running your own Bittensor node gives you full control, but it comes with real operational cost: disk space for chain history, ongoing sync and upgrade maintenance, monitoring, and the expertise to debug Substrate issues. For a team whose product is a subnet, a miner, or an analytics tool, that is often time spent away from the thing you actually ship.

A managed RPC endpoint removes most of that overhead. You get a maintained connection to Finney mainnet, HTTP and WebSocket access, and a support path when something breaks. The tradeoff is that you depend on the provider for availability and rate limits, which is why the evaluation criteria above matter.

A middle path is a dedicated node: isolated resources for your workload without the burden of running the hardware yourself. That is usually the right step when your traffic is predictable and high, or when shared rate limits start to interfere with your polling loops.

Key Takeaways

  • Bittensor runs on the Finney mainnet and uses Substrate JSON-RPC over HTTP and WebSocket, not the Ethereum method set.
  • Match your endpoint choice to your workload: exploratory scripts can use a public endpoint, while dashboards, monitors, and indexers need shared or dedicated capacity.
  • Always verify system_health and system_chain before trusting an endpoint, and compare block heights across endpoints when something looks stale.
  • Scale TAO values by 1e9 and read storage keys from live metadata, because runtime upgrades rename modules and storage items.
  • Use WebSocket subscriptions for real-time data, and always implement reconnect logic with backoff.
  • Evaluate providers on transport support, archive access, throughput, rate limit transparency, upgrade handling, and failover.

Frequently Asked Questions

Is Bittensor an EVM chain?

No. Bittensor is a Substrate-based chain, so it uses Substrate JSON-RPC methods such as system_health, chain_getHeader, and state_getStorage. Ethereum tools like eth_getBalance do not apply here; use the Polkadot.js API or another Substrate client instead.

What is the difference between Bittensor and Finney?

Bittensor is the network and the project, while Finney is the name of the mainnet. When you connect to a Bittensor RPC endpoint, you are connecting to Finney mainnet and reading its chain state.

Can I use a public RPC endpoint for production?

Public endpoints are fine for prototyping and low-frequency scripts. For production dashboards, monitoring loops, or indexers, shared or dedicated endpoints give you more predictable throughput and fewer surprises from rate limits.

Why do my TAO balances look wrong?

TAO uses 9 decimals. If you display raw integer values without scaling by 1e9, balances and emissions will appear far too large. Always convert before showing values to users.

How do I get real-time Bittensor data?

Use a WebSocket endpoint and subscribe to new heads or system events. Implement reconnect logic with backoff, and re-subscribe after each reconnect so your application does not run on stale data.

Where can I find OnFinality's Bittensor endpoint details?

See the Bittensor network page for endpoint and transport details, and the RPC pricing page to compare plans. A full list of chains is available on the supported RPC networks page.

RPC Knowledge Base

Related RPC details

Never Worry about Infrastructure Again

OnFinality takes away the heavy lifting of DevOps so you can build smarter and faster.

Get Started