Subscription API Quickstart

Learn how to subscribe to pending transactions, log events, new blocks and more using WebSockets on Ethereum, Polygon, Arbitrum, and Optimism.

What are WebSockets and how do they differ from HTTP?

WebSockets is a bidirectional communication protocol that maintains a network connection between a server and a client. Unlike HTTP, with WebSockets clients don't need to continuously make requests when they want information.

Instead, an open WebSocket connection can push network updates to clients by allowing them to subscribe to certain network states, such as new transactions or blocks being added to the blockchain.


Get Started

Use the Alchemy SDK

The Alchemy SDK is the easiest way to start using WebSockets. It exposes WebSockets support via the Ethers.js syntax. In addition, it exposes an additional Enhanced APIs created by Alchemy.

See an example below:

// Setup: npm install alchemy-sdk
import { Alchemy } from "alchemy-sdk";

// Optional config object, but defaults to demo api-key and eth-mainnet.
const settings = {
  apiKey: "demo", // Replace with your Alchemy API Key.
  network: Network.ETH_MAINNET, // Replace with your network.
};

const alchemy = new Alchemy(settings);

// Subscription for new blocks on Eth Mainnet.
alchemy.ws.on("block", (blockNumber) =>
  console.log("The latest block number is", blockNumber)
);

// Subscription for Alchemy's pendingTransactions Enhanced API
alchemy.ws.on(
  {
    method: "alchemy_pendingTransactions",
    toAddress: "vitalik.eth",
  },
  (tx) => console.log(tx)
);

👍

Automatic Retries on the Alchemy SDK

The Alchemy SDK automatically adds retry handling for WebSocket failures with no configuration necessary.

Alchemy SDK's Subscription Methods

These are the methods that you can call to begin a subscription. For types of events you can subscribe to, see Alchemy SDK's Event Types.

The Alchemy SDK's WebSockets is built on top of Ethers.js's implementation of WebSockets, so the majority of the syntax will be identical.

provider.on( eventName , listener ) ⇒ this

  • Add a listener to be triggered for each eventName event.

provider.once( eventName , listener ) ⇒ this

  • Add a listener to be triggered for only the next eventName event, at which time it will be removed.

provider.emit( eventName , ...args ) ⇒ boolean

  • Notify all listeners of the eventName event, passing args to each listener. This is generally only used internally.

provider.off( eventName [ , listener ] ) ⇒ this

  • Remove a listener for the eventName event. If no listener is provided, all listeners for eventName are removed.

provider.removeAllListeners( [ eventName ] ) ⇒ this

  • Remove all the listeners for the eventName events. If no eventName is provided, all events are removed.

provider.listenerCount( [ eventName ] ) ⇒ number

  • Returns the number of listeners for the eventName events. If no eventName is provided, the total number of listeners is returned.

provider.listeners( eventName ) ⇒ Array< Listener >

  • Returns the list of Listeners for the eventName events.

Alchemy SDK's Event Types

block (newHeads)

Emitted when a new block is mined.

import { Alchemy } from "alchemy-sdk";
const alchemy = new Alchemy();

// Subscribe to new blocks, or newHeads
alchemy.ws.on("block", (blockNumber) =>
  console.log("Latest block:", blockNumber)
);

pendingTransactions

Emitted when a new transaction enters the memory pool. Alchemy's custom implementation of this endpoint allows you to filter based on fromAddress or toAddress, the address a transaction was sent to or received from.

import { Alchemy } from "alchemy-sdk";
const alchemy = new Alchemy();

// Subscription for Alchemy's pendingTransactions API
alchemy.ws.on(
  {
    method: "alchemy_pendingTransactions",
    toAddress: "vitalik.eth",
    fromAddress: "0xshah.eth",
  },
  (tx) => console.log(tx)
);

transactions

Emitted when a specified transaction has been mined.

import { Alchemy } from "alchemy-sdk";
const alchemy = new Alchemy();

const txHash = "0xfc89ec10998a74c37a107535ca1cf8714edad409bff40d6da9e8a436cef6daad";

// Subscription for a specific transaction to be mined
alchemy.ws.on(
  txHash,
  (tx) => console.log(tx)
);

logs

A filter is an object, representing a contract log Filter, which has the optional properties address (the source contract) and topics (a topic-set to match).

If address is unspecified, the filter matches any contract address.

import { Alchemy } from "alchemy-sdk";
const alchemy = new Alchemy();

// This filter could also be generated with the Contract or
// Interface API. If address is not specified, any address
// matches and if topics is not specified, any log matches
const filter = {
  address: "dai.tokens.ethers.eth",
  topics: [
    utils.id("Transfer(address,address,uint256)")
  ]
}
alchemy.ws.on(filter, (log, event) => {
  // Emitted whenever a DAI token transfer occurs
})

// Notice this is an array of topic-sets and is identical to
// using a filter with no address (i.e. match any address)
const topicSets = [
  utils.id("Transfer(address,address,uint256)"),
  null,
  [
    hexZeroPad(myAddress, 32),
    hexZeroPad(myOtherAddress, 32)
  ]
]
alchemy.ws.on(topicSets, (log, event) => {
  // Emitted any token is sent TO either address
})

Using JSON-RPC Requests to Access WebSockets

Alternatively, you can use the low-level eth_subscribe and eth_unsubscribe JSON-RPC methods to access WebSockets.

To begin, open a WebSocket using the WebSocket URL for your app. You can find your app's WebSocket URL by opening the app's page in your dashboard and clicking "View Key".

Note that your app's URL for WebSockets is different from its URL for HTTP requests, but both can be found by clicking "View Key".

600600

Next, install a command line tool for making WebSocket requests such as wscat. Using wscat, you can send requests as follows:

$ wscat -c wss://eth-mainnet.ws.alchemyapi.io/ws/demo

// create subscription
> {"id": 1, "method": "eth_subscribe", "params": ["newHeads"]}
< {"jsonrpc":"2.0","id":1,"result":"0xcd0c3e8af590364c09d0fa6a1210faf5"}

// incoming notifications
< {"jsonrpc":"2.0","method":"eth_subscription","params":{"subscription":"0xcd0c3e8af590364c09d0fa6a1210faf5","result":{"difficulty":"0xd9263f42a87",<...>, "uncles":[]}}}
< {"jsonrpc":"2.0","method":"eth_subscription","params":{"subscription":"0xcd0c3e8af590364c09d0fa6a1210faf5","result":{"difficulty":"0xd90b1a7ad02", <...>, "uncles":["0x80aacd1ea4c9da32efd8c2cc9ab38f8f70578fcd46a1a4ed73f82f3e0957f936"]}}}

// cancel subscription
> {"id": 1, "method": "eth_unsubscribe", "params": ["0xcd0c3e8af590364c09d0fa6a1210faf5"]}
< {"jsonrpc":"2.0","id":1,"result":true}

❗️

Don't Use HTTP Methods Over WebSockets!

Though it's currently possible to send all your HTTP requests over Websockets, we discourage our developers from doing so. Instead, you should only send eth_subscribe and eth_unsubscribe requests to WebSockets.

This is for several reasons:

  • You won't receive HTTP status codes in WebSockets responses, which can be useful and actionable.
  • Because individual HTTP requests are load-balanced in our infrastructure to the fastest possible server, you'll add additional latency by sending JSON-RPC requests over WebSockets.
  • WebSockets client-side handling has many tricky edge cases and silent failure modes, which can make your dApp less stable.

JSON-RPC Subscription Types

The following subscription types are accepted in all eth_subscribe WebSocket requests through your Alchemy SDK endpoint.

Subscription Type

Description

alchemy_pendingTransactions

Emits full transactions that are sent to the network, marked as "pending", and are sent from or to a certain address.

newPendingTransactions

Emits transaction hashes that are sent to the network and marked as "pending".

newHeads

Emits new blocks that are added to the blockchain.

logs

Emits logs attached to a new block that match certain topic filters.


JSON-RPC Subscription Type Support Per Chain

👍

WebSockets Docs Separated By Chain

To browse the request and response parameters for supported WebSockets requests, click on the corresponding Chain title below. Not all subscription types are supported for all chains yet.

Chain

alchemy_pendingTransactions

newPendingTransactions

newHeads

logs

Ethereum

:white-check-mark:

:white-check-mark:

:white-check-mark:

:white-check-mark:

Polygon

:white-check-mark:

:white-check-mark:

:white-check-mark:

:white-check-mark:

Arbitrum

:x:

:x:

:white-check-mark:

:white-check-mark:

Optimism

:x:

:x:

:white-check-mark:

:white-check-mark:


WebSocket Limits

The following limits apply for WebSocket connections:

  • There is a limit of 20,000 WebSocket connections per API Key as well as 1,000 parallel WebSocket subscriptions per WebSocket connection, creating a maximum of 20 million subscriptions per application.
  • The maximum size of a JSON-RPC batch request that can be sent over a WebSocket connection is 20
  • Free tier users will be limited to 10 concurrent requests per WebSocket connection.

Error Codes

Error Code

Error Message

Solution

32600

"The maximum batch size that can be sent over a websocket connection is 10. Please decrease the batch size and try again."

Occurs when user attempts to send high-volume JSON-RPC traffic over Websockets. We recommend this traffic be sent over HTTP instead to optimize server backends.


Example Projects