# Connecting to Bitcoin Core's ZeroMQ Interface Over Tor

**URL:** https://community.start9.com/t/connecting-to-bitcoin-cores-zeromq-interface-over-tor/2212
**Category:** DIY Community
**Created:** [December 14, 2024, 8:35am UTC](https://community.start9.com/t/connecting-to-bitcoin-cores-zeromq-interface-over-tor/2212 "2024-12-14T08:35:35Z")
**Posts on this page:** 2
**Page:** 1

<div class="post-metadata">

### Author: ![matt7](https://community.start9.com/letter_avatar_proxy/v4/letter/m/9fc29f/32.png) [@matt7](https://community.start9.com/u/matt7)
#### Post date: [December 14, 2024, 8:35am UTC](https://community.start9.com/t/connecting-to-bitcoin-cores-zeromq-interface-over-tor/2212/1 "2024-12-14T08:35:35Z")

</div>

Under Bitcoin Core’s listed interfaces, I see the ZeroMQ interface with an .onion address (no .local option). I’m having trouble connecting to it. I know this is a long shot, but has anyone successfully connected to this interface?

I have not been successful with Python’s PyZMQ library. I did find an example in Bitcoin Core’s repo: [bitcoin/contrib/zmq/zmq\_sub.py at master · bitcoin/bitcoin · GitHub](https://github.com/bitcoin/bitcoin/blob/master/contrib/zmq/zmq_sub.py), but I could not get it to work.

I have the Tor daemon running and can access .onion sites using the requests library, so I know Tor is working. A simple example that returns the first 500 characters of an .onion URL:

```python
import requests

onion_url = "http://some-onion-address.onion"
proxies = {
    "http": "socks5h://127.0.0.1:9050",
    "https": "socks5h://127.0.0.1:9050",
}

try:
    response = requests.get(onion_url, proxies=proxies, timeout=10)
    print("Status Code:", response.status_code)
    print("Response Text:", response.text[:500])
except requests.exceptions.RequestException as e:
    print("Failed to connect to .onion site:", e)

```

Interestingly, if I set onion\_url to `http://my-bitcoin-core-zeromq-address.onion:28333`, I get a ZMQ message (or part of one) from my node embedded in the exception message! Obviously, the error is because I’m trying to use the requests library (using the HTTP protocol) on a socket publishing data using the ZMQ protocol, but you can see the ZMQ topic “hashtx” appears at byte 12:

> Failed to connect to .onion site: (‘Connection aborted.’, BadStatusLine(“ÿ\x00\x00\x00\x00\x00\x00\x00\x01\x7f\x07\x01`hashtx`!\x01\x06\x0c`...full tx hash scrubbed`”))

Any ideas on getting PyZMQ to work? Here’s the minimal example I was expecting to work based on what I’ve read:

> **ZMQ Over Tor Attempt**
>
> ```python
> import zmq
> import socket
> import socks
> import time
> 
> zmq_addr = 'tcp://my-bitcoin-core-zeromq-address.onion:28333'
> timeout = 30
> 
> socks.set_default_proxy(socks.SOCKS5, '127.0.0.1', 9050)
> socket.socket = socks.socksocket
> 
> zmq_context = zmq.Context()
> zmq_socket = zmq_context.socket(zmq.SUB)
> zmq_socket.setsockopt(zmq.RCVHWM, 0)
> for topic in ['hashblock', 'hashtx', 'rawblock', 'rawtx', 'sequence']:
> zmq_socket.setsockopt_string(zmq.SUBSCRIBE, topic)
> zmq_socket.connect(zmq_addr)
> 
> start_time = time.time()
> while (start_time + timeout > time.time()):
> try:
> message = zmq_socket.recv_multipart(flags=zmq.NOBLOCK)
> print(f'Received message: {message}')
> except zmq.Again:
> continue # no message
> except Exception as e:
> print(f'Error: {e}', exc_info=True)
> 
> zmq_socket.close()
> zmq_context.destroy()
> 
> ```

---

<div class="post-metadata">

### Author: ![matt7](https://community.start9.com/letter_avatar_proxy/v4/letter/m/9fc29f/32.png) [@matt7](https://community.start9.com/u/matt7)
#### Post date: [December 14, 2024, 8:54am UTC](https://community.start9.com/t/connecting-to-bitcoin-cores-zeromq-interface-over-tor/2212/2 "2024-12-14T08:54:51Z")

</div>

Well, I worked on this for two days, finally decided to ask the internet, and then stumbled across the answer 20 min later. Oh well, I’ll take it!

The answer is that I needed to set this option:

`zmq_socket.setsockopt_string(zmq.SOCKS_PROXY, '127.0.0.1:9050')`

(And the socket to socksocket monkey patching can be removed.)
