Block explorer web interface based on the esplora-electrs HTTP API.
Written as a single-page app in a reactive and functional style using rxjs and cycle.js.
See live at Blockstream.info.
API documentation is available here.
Join the translation efforts on Transifex.

Explore blocks, transactions and addresses
Support for Segwit and Bech32 addresses
Shows previous output and spending transaction details
Quick-search for txid, address, block hash or height by navigating to /<query>
Advanced view with script hex/assembly, witness data, outpoints and more
Mobile-ready responsive design
Translated to 17 languages
Noscript support
For Liquid and other Elements-based chains: support for CT, peg-in/out transactions and multi-asset
Mainnet, Testnet and Elements high performance electrum server
To start a development server with live babel/browserify transpilation, run:
$ git clone https://github.com/Blockstream/esplora && cd esplora
$ npm install
$ export API_URL=http://localhost:3000/ # or https://blockstream.info/api/ if you don't have a local API server
# (see more config options below)
$ npm run dev-server
The server will be available at http://localhost:5000/
To display debugging information for the Rx streams in the web developer console, set localStorage.debug = '*' and refresh.
Browser polling uses three shared cadence tiers defined in client/src/const.js:
View-scoped polls run only while their view is active and the browser window is focused. Their first tick occurs after a full interval because route entry already requests the initial data. This avoids sending duplicate requests when opening a page. The chain tip is global and also refreshes immediately when the application starts or a block, transaction, or address page is opened.
The block list refreshes when the chain tip height changes, with the slow safety poll covering same-height reorganizations. Confirmed peg state and peg chain transactions also refresh on new blocks rather than on a timer. A newly observed tip resets pending block template polling and delays the next request by 15 seconds so the electrs cache can refresh.
The dashboard requests both /mempool/recent and /mempool because they serve
different UI contracts. /mempool/recent supplies the recent transaction list;
/mempool supplies aggregate backlog fields such as transaction count, virtual
size, total fees, and the fee histogram used by congestion and transaction fee
analysis.
To build the static assets directory for production deployment, set config options (see below)
and run $ npm run dist. The files will be created under dist/.
Because Esplora is a single-page app, the HTTP server needs to be configured to serve the index.html file in reply to missing pages.
See contrib/nginx.conf.in for example nginx configuration (TL;DR: try_files $uri /index.html).
Production builds create content-hashed copies of the app, stylesheets, lazy-loaded
scripts and fonts referenced directly by the stylesheets by default. Original
filenames are retained for rollback and cached HTML. asset-manifest.json in the
output directory (dist/, or DEST) maps original relative paths to hashed paths.
Set HASH_ASSETS=0 to disable hashing and use plain filenames without a manifest.
Both server-side renderers accept ASSET_MANIFEST pointing to this file (default:
DEST/asset-manifest.json, or the project's dist/asset-manifest.json). Missing
manifests fall back to plain filenames; STATIC_ROOT is applied to either form.
Deployment must upload new hashed files with
Cache-Control: public, max-age=31536000, immutable before updating HTML, and
must not delete old hashed files immediately after deployment (cached HTML and
open tabs still reference them). If the server falls back to index.html for
unknown paths, hashed-asset misses must return a real 404 instead, so a missing
file is never cached as HTML.
To start a pre-rendering server that generates static HTML replies suitable for noscript users, run:
# (clone, cd, "npm install" and configure as above)
$ export STATIC_ROOT=http://localhost:5000/ # for loading CSS, images and fonts
$ npm run prerender-server
The server will be available at http://localhost:5001/
All options are optional.
NODE_ENV - set to production to enable js minification, or to development to disable (defaults to production)BASE_HREF - base href for user interface (defaults to /, change if not served from the root directory)BASE_PREFIX - optional path prefix prepended to each flavor's BASE_HREF, to serve the whole multi-network site under a sub-directory (e.g. BASE_PREFIX=preview serves /preview/, /preview/signet/, ...). API_URL is left un-prefixed so a prefixed build still uses the same backendSTATIC_ROOT - root for static assets (defaults to BASE_HREF, change to load static assets from a different server)API_URL - URL for HTTP REST API (defaults to /api, change if the API is available elsewhere)CANONICAL_URL - absolute base url for user interface (optional, only required for opensearch and canonical link tags)NATIVE_ASSET_LABEL - the name of the network native asset (defaults to BTC)TARGET_BLOCK_INTERVAL_SECONDS - expected time between blocks, used for confirmation ETAs (defaults to 60 for Elements chains and 600 otherwise)SITE_TITLE - website title for <title> (defaults to Block Explorer)SITE_DESC - meta description (defaults to Esplora Block Explorer)HOME_TITLE - text for homepage title (defaults to SITE_TITLE)SITE_FOOTER - text for page footer (defaults to Powered by esplora)HEAD_HTML - custom html to inject at the end of <head>FOOT_HTML - custom html to inject at the end of <body>CUSTOM_ASSETS - space separated list of static assets to add to the buildCUSTOM_CSS - space separated list of css files to append into style.cssNOSCRIPT_REDIR - redirect noscript users to {request_path}?nojs (should be captured server-side and redirected to the prerender server, also see NOSCRIPT_REDIR_BASE in dev server options)NAVBAR_HTML - display navigation barNote that API_URL should be set to the publicly-reachable URL where the user's browser can issue requests at.
(that is, not via localhost, unless you're setting up a dev environment where the browser is running on the same machine as the API server.)
Elements-only configuration:
IS_ELEMENTS - set to 1 to indicate this is an Elements-based chain (enables asset issuance and Elements-specific features)SHOW_HIGH_VALUE_ASSETS - set to 1 to show circulating values for selected assets on the Liquid mainnet dashboard (enabled by the Liquid mainnet flavor)NATIVE_ASSET_ID - the ID of the native asset used to pay fees (defaults to 6f0279e9ed041c3d710a9f57d0c02928416460c4b722ae3457a11eec381c526d, the asset id for LBTC)BLIND_PREFIX - the base58 address prefix byte used for confidential addresses (defaults to 12)PARENT_CHAIN_EXPLORER_TXOUT - URL format for linking to transaction outputs on the parent chain, with {txid} and {vout} as placeholders. Example: https://blockstream.info/tx/{txid}#output:{vout}PARENT_CHAIN_EXPLORER_ADDRESS - URL format for linking to addresses on parent chain, with {addr} replaced by the address. Example: https://blockstream.info/address/{addr}ASSET_MAP_URL - url to load json asset map (in the "minimal" format)Menu configuration (useful for inter-linking multiple instances on different networks):
MENU_ITEMS - json map of menu items, where the key is the label and the value is the urlMENU_ACTIVE - the active menu item identified by its labelAll GUI options, plus:
PORT - port to bind http development server (defaults to 5000)CORS_ALLOW - value to set for Access-Control-Allow-Origin header (optional)NOSCRIPT_REDIR_BASE - base url for prerender server, for redirecting ?nojs requests (should be set alongside NOSCRIPT_REDIR)All GUI options, plus:
PORT - port to bind pre-rendering server (defaults to 5001)Note that unlike the regular JavaScript-based app that sends API requests from the client-side,
the pre-rendering server sends API requests from the server-side. This means that API_URL should
be configured to the URL reachable by the server, typically http://localhost:3000/.
Build the base image first:
docker build -t blockstream/esplora-base -f contrib/Dockerfile.base .
then the main image:
docker build -t esplora -f contrib/Dockerfile .
Alternatively, you may use the pre-built blockstream/esplora image from Docker Hub. The latest tag tracks the master branch; release tags (e.g. esplora_v2.10) are also published as versioned image tags (e.g. blockstream/esplora:v2.10) that can be pinned for reproducible deployments.
docker run -p 50001:50001 -p 8080:80 \
--volume $PWD/data_bitcoin_mainnet:/data \
--rm -i -t esplora \
bash -c "/srv/explorer/run.sh bitcoin-mainnet explorer"
docker run -p 50001:50001 -p 8082:80 \
--volume $PWD/data_liquid_mainnet:/data \
--rm -i -t esplora \
bash -c "/srv/explorer/run.sh liquid-mainnet explorer"
docker run -p 50001:50001 -p 8084:80 \
--volume $PWD/data_bitcoin_testnet:/data \
--rm -i -t esplora \
bash -c "/srv/explorer/run.sh bitcoin-testnet explorer"
docker run -p 50001:50001 -p 8084:80 \
--volume $PWD/data_bitcoin_testnet4:/data \
--rm -i -t esplora \
bash -c "/srv/explorer/run.sh bitcoin-testnet4 explorer"
docker run -p 50001:50001 -p 8084:80 \
--volume $PWD/data_bitcoin_signet:/data \
--rm -i -t esplora \
bash -c "/srv/explorer/run.sh bitcoin-signet explorer"
docker run -p 50001:50001 -p 8096:80 \
--volume $PWD/data_liquid_testnet:/data \
--rm -i -t esplora \
bash -c "/srv/explorer/run.sh liquid-testnet explorer"
docker run -p 50001:50001 -p 8092:80 \
--volume $PWD/data_liquid_regtest:/data \
--rm -i -t esplora \
bash -c "/srv/explorer/run.sh liquid-regtest explorer"
docker run -p 50001:50001 -p 8094:80 \
--volume $PWD/data_bitcoin_regtest:/data \
--rm -i -t esplora \
bash -c "/srv/explorer/run.sh bitcoin-regtest explorer"
When run for Bitcoin regtest or Liquid regtest, the esplora container will
create a default wallet and mine 100 blocks internally. You can disable this behavior
by setting NO_REGTEST_MINING=1.
Set -e DEBUG=verbose to enable more verbose logging.
Set -e NO_PRECACHE=1 to disable pre-caching of statistics for "popular addresses",
which may take a long time and is not necessary for personal use.
Set -e NO_ADDRESS_SEARCH=1 to disable the by-prefix address search index.
Set -e ENABLE_LIGHTMODE=1 to enable esplora-electrs's light mode.
Set -e ONION_URL=http://xyz.onion to enable the Onion-Location header.
blockstream/tor:latestRun: docker -d --name hidden_service blockstream/tor:latest tor -f /home/tor/torrc (could add a -v /extra/torrc:/home/tor/torrc, if you have a custom torrc)
Example torrc:
DataDirectory /home/tor/tor
PidFile /var/run/tor/tor.pid
ControlSocket /var/run/tor/control GroupWritable RelaxDirModeCheck
ControlSocketsGroupWritable 1
SocksPort unix:/var/run/tor/socks WorldWritable
SocksPort 9050
CookieAuthentication 1
CookieAuthFileGroupReadable 1
CookieAuthFile /var/run/tor/control.authcookie
Log [handshake]debug [*]notice stderr
HiddenServiceDir /home/tor/tor/hidden_service_v3/
HiddenServiceVersion 3
HiddenServicePort 80 127.0.0.1:80
MIT
324 followers · starred Dec 2018
494 followers · starred Sep 2019
564 followers · starred Mar 2021
597 followers · starred Apr 2019
Block explorer web interface based on the esplora-electrs HTTP API.
Written as a single-page app in a reactive and functional style using rxjs and cycle.js.
See live at Blockstream.info.
API documentation is available here.
Join the translation efforts on Transifex.

Explore blocks, transactions and addresses
Support for Segwit and Bech32 addresses
Shows previous output and spending transaction details
Quick-search for txid, address, block hash or height by navigating to /<query>
Advanced view with script hex/assembly, witness data, outpoints and more
Mobile-ready responsive design
Translated to 17 languages
Noscript support
For Liquid and other Elements-based chains: support for CT, peg-in/out transactions and multi-asset
Mainnet, Testnet and Elements high performance electrum server
To start a development server with live babel/browserify transpilation, run:
$ git clone https://github.com/Blockstream/esplora && cd esplora
$ npm install
$ export API_URL=http://localhost:3000/ # or https://blockstream.info/api/ if you don't have a local API server
# (see more config options below)
$ npm run dev-server
The server will be available at http://localhost:5000/
To display debugging information for the Rx streams in the web developer console, set localStorage.debug = '*' and refresh.
Browser polling uses three shared cadence tiers defined in client/src/const.js:
View-scoped polls run only while their view is active and the browser window is focused. Their first tick occurs after a full interval because route entry already requests the initial data. This avoids sending duplicate requests when opening a page. The chain tip is global and also refreshes immediately when the application starts or a block, transaction, or address page is opened.
The block list refreshes when the chain tip height changes, with the slow safety poll covering same-height reorganizations. Confirmed peg state and peg chain transactions also refresh on new blocks rather than on a timer. A newly observed tip resets pending block template polling and delays the next request by 15 seconds so the electrs cache can refresh.
The dashboard requests both /mempool/recent and /mempool because they serve
different UI contracts. /mempool/recent supplies the recent transaction list;
/mempool supplies aggregate backlog fields such as transaction count, virtual
size, total fees, and the fee histogram used by congestion and transaction fee
analysis.
To build the static assets directory for production deployment, set config options (see below)
and run $ npm run dist. The files will be created under dist/.
Because Esplora is a single-page app, the HTTP server needs to be configured to serve the index.html file in reply to missing pages.
See contrib/nginx.conf.in for example nginx configuration (TL;DR: try_files $uri /index.html).
Production builds create content-hashed copies of the app, stylesheets, lazy-loaded
scripts and fonts referenced directly by the stylesheets by default. Original
filenames are retained for rollback and cached HTML. asset-manifest.json in the
output directory (dist/, or DEST) maps original relative paths to hashed paths.
Set HASH_ASSETS=0 to disable hashing and use plain filenames without a manifest.
Both server-side renderers accept ASSET_MANIFEST pointing to this file (default:
DEST/asset-manifest.json, or the project's dist/asset-manifest.json). Missing
manifests fall back to plain filenames; STATIC_ROOT is applied to either form.
Deployment must upload new hashed files with
Cache-Control: public, max-age=31536000, immutable before updating HTML, and
must not delete old hashed files immediately after deployment (cached HTML and
open tabs still reference them). If the server falls back to index.html for
unknown paths, hashed-asset misses must return a real 404 instead, so a missing
file is never cached as HTML.
To start a pre-rendering server that generates static HTML replies suitable for noscript users, run:
# (clone, cd, "npm install" and configure as above)
$ export STATIC_ROOT=http://localhost:5000/ # for loading CSS, images and fonts
$ npm run prerender-server
The server will be available at http://localhost:5001/
All options are optional.
NODE_ENV - set to production to enable js minification, or to development to disable (defaults to production)BASE_HREF - base href for user interface (defaults to /, change if not served from the root directory)BASE_PREFIX - optional path prefix prepended to each flavor's BASE_HREF, to serve the whole multi-network site under a sub-directory (e.g. BASE_PREFIX=preview serves /preview/, /preview/signet/, ...). API_URL is left un-prefixed so a prefixed build still uses the same backendSTATIC_ROOT - root for static assets (defaults to BASE_HREF, change to load static assets from a different server)API_URL - URL for HTTP REST API (defaults to /api, change if the API is available elsewhere)CANONICAL_URL - absolute base url for user interface (optional, only required for opensearch and canonical link tags)NATIVE_ASSET_LABEL - the name of the network native asset (defaults to BTC)TARGET_BLOCK_INTERVAL_SECONDS - expected time between blocks, used for confirmation ETAs (defaults to 60 for Elements chains and 600 otherwise)SITE_TITLE - website title for <title> (defaults to Block Explorer)SITE_DESC - meta description (defaults to Esplora Block Explorer)HOME_TITLE - text for homepage title (defaults to SITE_TITLE)SITE_FOOTER - text for page footer (defaults to Powered by esplora)HEAD_HTML - custom html to inject at the end of <head>FOOT_HTML - custom html to inject at the end of <body>CUSTOM_ASSETS - space separated list of static assets to add to the buildCUSTOM_CSS - space separated list of css files to append into style.cssNOSCRIPT_REDIR - redirect noscript users to {request_path}?nojs (should be captured server-side and redirected to the prerender server, also see NOSCRIPT_REDIR_BASE in dev server options)NAVBAR_HTML - display navigation barNote that API_URL should be set to the publicly-reachable URL where the user's browser can issue requests at.
(that is, not via localhost, unless you're setting up a dev environment where the browser is running on the same machine as the API server.)
Elements-only configuration:
IS_ELEMENTS - set to 1 to indicate this is an Elements-based chain (enables asset issuance and Elements-specific features)SHOW_HIGH_VALUE_ASSETS - set to 1 to show circulating values for selected assets on the Liquid mainnet dashboard (enabled by the Liquid mainnet flavor)NATIVE_ASSET_ID - the ID of the native asset used to pay fees (defaults to 6f0279e9ed041c3d710a9f57d0c02928416460c4b722ae3457a11eec381c526d, the asset id for LBTC)BLIND_PREFIX - the base58 address prefix byte used for confidential addresses (defaults to 12)PARENT_CHAIN_EXPLORER_TXOUT - URL format for linking to transaction outputs on the parent chain, with {txid} and {vout} as placeholders. Example: https://blockstream.info/tx/{txid}#output:{vout}PARENT_CHAIN_EXPLORER_ADDRESS - URL format for linking to addresses on parent chain, with {addr} replaced by the address. Example: https://blockstream.info/address/{addr}ASSET_MAP_URL - url to load json asset map (in the "minimal" format)Menu configuration (useful for inter-linking multiple instances on different networks):
MENU_ITEMS - json map of menu items, where the key is the label and the value is the urlMENU_ACTIVE - the active menu item identified by its labelAll GUI options, plus:
PORT - port to bind http development server (defaults to 5000)CORS_ALLOW - value to set for Access-Control-Allow-Origin header (optional)NOSCRIPT_REDIR_BASE - base url for prerender server, for redirecting ?nojs requests (should be set alongside NOSCRIPT_REDIR)All GUI options, plus:
PORT - port to bind pre-rendering server (defaults to 5001)Note that unlike the regular JavaScript-based app that sends API requests from the client-side,
the pre-rendering server sends API requests from the server-side. This means that API_URL should
be configured to the URL reachable by the server, typically http://localhost:3000/.
Build the base image first:
docker build -t blockstream/esplora-base -f contrib/Dockerfile.base .
then the main image:
docker build -t esplora -f contrib/Dockerfile .
Alternatively, you may use the pre-built blockstream/esplora image from Docker Hub. The latest tag tracks the master branch; release tags (e.g. esplora_v2.10) are also published as versioned image tags (e.g. blockstream/esplora:v2.10) that can be pinned for reproducible deployments.
docker run -p 50001:50001 -p 8080:80 \
--volume $PWD/data_bitcoin_mainnet:/data \
--rm -i -t esplora \
bash -c "/srv/explorer/run.sh bitcoin-mainnet explorer"
docker run -p 50001:50001 -p 8082:80 \
--volume $PWD/data_liquid_mainnet:/data \
--rm -i -t esplora \
bash -c "/srv/explorer/run.sh liquid-mainnet explorer"
docker run -p 50001:50001 -p 8084:80 \
--volume $PWD/data_bitcoin_testnet:/data \
--rm -i -t esplora \
bash -c "/srv/explorer/run.sh bitcoin-testnet explorer"
docker run -p 50001:50001 -p 8084:80 \
--volume $PWD/data_bitcoin_testnet4:/data \
--rm -i -t esplora \
bash -c "/srv/explorer/run.sh bitcoin-testnet4 explorer"
docker run -p 50001:50001 -p 8084:80 \
--volume $PWD/data_bitcoin_signet:/data \
--rm -i -t esplora \
bash -c "/srv/explorer/run.sh bitcoin-signet explorer"
docker run -p 50001:50001 -p 8096:80 \
--volume $PWD/data_liquid_testnet:/data \
--rm -i -t esplora \
bash -c "/srv/explorer/run.sh liquid-testnet explorer"
docker run -p 50001:50001 -p 8092:80 \
--volume $PWD/data_liquid_regtest:/data \
--rm -i -t esplora \
bash -c "/srv/explorer/run.sh liquid-regtest explorer"
docker run -p 50001:50001 -p 8094:80 \
--volume $PWD/data_bitcoin_regtest:/data \
--rm -i -t esplora \
bash -c "/srv/explorer/run.sh bitcoin-regtest explorer"
When run for Bitcoin regtest or Liquid regtest, the esplora container will
create a default wallet and mine 100 blocks internally. You can disable this behavior
by setting NO_REGTEST_MINING=1.
Set -e DEBUG=verbose to enable more verbose logging.
Set -e NO_PRECACHE=1 to disable pre-caching of statistics for "popular addresses",
which may take a long time and is not necessary for personal use.
Set -e NO_ADDRESS_SEARCH=1 to disable the by-prefix address search index.
Set -e ENABLE_LIGHTMODE=1 to enable esplora-electrs's light mode.
Set -e ONION_URL=http://xyz.onion to enable the Onion-Location header.
blockstream/tor:latestRun: docker -d --name hidden_service blockstream/tor:latest tor -f /home/tor/torrc (could add a -v /extra/torrc:/home/tor/torrc, if you have a custom torrc)
Example torrc:
DataDirectory /home/tor/tor
PidFile /var/run/tor/tor.pid
ControlSocket /var/run/tor/control GroupWritable RelaxDirModeCheck
ControlSocketsGroupWritable 1
SocksPort unix:/var/run/tor/socks WorldWritable
SocksPort 9050
CookieAuthentication 1
CookieAuthFileGroupReadable 1
CookieAuthFile /var/run/tor/control.authcookie
Log [handshake]debug [*]notice stderr
HiddenServiceDir /home/tor/tor/hidden_service_v3/
HiddenServiceVersion 3
HiddenServicePort 80 127.0.0.1:80
MIT
324 followers · starred Dec 2018
494 followers · starred Sep 2019
564 followers · starred Mar 2021
597 followers · starred Apr 2019