I have been trying to get the IP address of the tor exit node from a bash script. I have tried torifying the usual methods found in various posts in forums for getting one's local IP address. For example:

torify wget -qO- http://ipecho.net/plain ; echo
torify curl -s https://check.torproject.org/ | grep "Your IP address appears to be:" | grep -o '\(\d\{1,3\}\.\)\{3\}\d\{1,3\}'

All these methods return a different IP address than that given by check.torproject.org or any IP identifying site from the browser configured to use tor as a proxy.

I modified the stem script from https://stackoverflow.com/a/17130011 to get the exit relays and compare the results with that given by the bash shell command:


from stem import Signal
import os
import time

from stem import CircStatus
from stem.control import Controller

with Controller.from_port(port = 9051) as controller:
  controller.signal(Signal.NEWNYM) # get new tor identity


print "Exit relays:"

with Controller.from_port(port = 9051) as controller:

  for circ in controller.get_circuits():
    if circ.status != CircStatus.BUILT:

    exit_fp, exit_nickname = circ.path[-1]
    exit_desc = controller.get_network_status(exit_fp, None)
    exit_address = exit_desc.address if exit_desc else 'unknown' # get relay IP

    print exit_address

print "wget:"

os.system("torify wget -qO- http://ipecho.net/plain ; echo")
os.system("open 'https://check.torproject.org/'")

and I find that the first address is usually the correct address of the exit node and the second address is usually that given by the bash command:

Exit relays:


Exit relays:


Exit relays:


Exit relays:


So is the address gotten by wget or curl the entry node or what…, and why? How can I get the EXIT node from bash?

  • If you install and run iftop, you can see the IPs of all directly-connected Tor relays. In none of my tests did I see direct connections to an IP reported by "torify wget -qO- ipecho.net/plain ; echo". Could it be the exit-associated DNS server?
    – mirimir
    Jul 27, 2014 at 9:13
  • Also, browsing ipecho.net/plain reports the same exit IP that check.torproject.org reports. What does "wget -qO-" accomplish? The wget manpage doesn't clearly say.
    – mirimir
    Jul 27, 2014 at 9:21
  • That's what I was saying in the OP. -q = --quiet and -O- = --output-document=stdout.
    – hmj6jmh
    Jul 27, 2014 at 16:20
  • What filters and options did you use for iftop? Is there any way to show only port 9050 traffic? What exact command did you use? As for direct connections to torify wget IP, stem does report them as shown in my examples.
    – hmj6jmh
    Jul 27, 2014 at 16:21
  • I just run "sudo iftop". I still don't get wget -qO-. Accessing ipecho.net in Tor browser gives the exit relay's IP. So what is wget reporting? Whatever it is, it's a Tor relay.
    – mirimir
    Jul 28, 2014 at 5:57

4 Answers 4


If your configured Tor socks port is 9150, then you can try this command:

curl --socks5-hostname localhost:9150 http://ipecho.net/plain

You also can configure it by editing your config file (usually named torrc) or pass an option named socksport as command-line argument when executing Tor.

  • Yes it is configured for port 9150 by default. This command yielded curl: (7) couldn't connect to host. I don't understand how this would work differently though. torify would send the command through the same port wouldn't it?
    – hmj6jmh
    Jul 27, 2014 at 8:23

The browser and bash are using different circuits, with different exits. The stem script shows exits for all active circuits.

Also, try my tweaked exit_used.py script.

  • The stem script doesn't show all the exit nodes and hops that tor shows. tor: Chose exit server '$2248CFE8C6E414D580C9C600EB16239EABE6E330=Paul20666RO at' First hop: finished sending CREATE_FAST cell to '$22BCD0DFD148209C9860C7F89907AB4DEE974A08~Fastnet at' Chose exit server '$E34E25D958D46DDE5092385B14117C9B301DC0E9=AccessNow13 at' First hop: finished sending CREATE_FAST cell to '$7C1542958F11DB68B9D812F92E655CDE49AC28AA~PPTOR0035 at' stem script: Exit relays:
    – hmj6jmh
    Jul 31, 2014 at 17:10
  • OK, true. The question then is how to know which circuit is being used for which process. Is there a variable from stem to indicate that? Or maybe link to something from netstat?
    – mirimir
    Jul 31, 2014 at 17:49
  • I tried your modified script and it shows the entry node when I run my script above and the exit node when I open ipecho.net/plain in the browser.
    – hmj6jmh
    Jul 31, 2014 at 22:17
  • That's confusing :( But I still think that you're just looking at exit relays for multiple circuits. Opening the saved "plain" file from running "torify wget ipecho.net/plain", I see a different IP address than from browsing "ipecho.net/plain". They're getting the same page, but through different circuits.
    – mirimir
    Jul 31, 2014 at 23:16
  • Yes, I agree. See my partial answer.
    – hmj6jmh
    Jul 31, 2014 at 23:21

Answer to question 1, part 1 (NOT the final answer):

I think I have the answer to the first half of my first question: is the address gotten by 'wget' or 'curl' the entry node?

My script gives:

Exit relays:


tor gives:

Jul 29 06:37:47.000 [info] const node_t *choose_good_exit_server_general(int, int)(): Chose exit server '$2248CFE8C6E414D580C9C600EB16239EABE6E330=Paul20666RO at'
Jul 29 06:37:48.000 [info] const node_t *choose_good_exit_server_general(int, int)(): Chose exit server '$E34E25D958D46DDE5092385B14117C9B301DC0E9=AccessNow13 at'

Going by the order that tor shows, the first 'exit server' is the entry node. Note that it is what wget gives. The last 'exit server' is the exit node. This is what the browser shows. I have tested this numerous times with my script and it is consistent.

What puzzles and alarms me is part 2 of question 1, why?. Somehow wget and curl are only getting as far as the entry node, which is then decrypting (that is, IF the traffic is even encrypted) and relaying the traffic to the destination IP, completely bypassing the rest of the tor circuit. The entry node is acting like a single-node circuit. Yet tor and the browser are showing the exit node of the multi-node circuit. Isn't this a serious breach of tor design philosophy? Think about it, some traffic is being short-circuited and decrypted and sent to its destination without the aid of all the hops and tor circuit nodes in between. Both wget and curl are the premier tools available to the command line for downloading information. Clearly any use of these tools is not being safeguarded, as expected, by the entire tor circuit. Protecting the identity of a user of these tools is just as important as protecting the identity of the browser user, maybe even more important. I want to know why and how come this hasn't been discovered and reported as a bug?

  • I think that you're misinterpreting the Tor log output that you've quoted. The two lines ( and are both exit servers, and wget is using Your "Exit relays" output shows them plus exits for two reserve circuits.
    – mirimir
    Aug 1, 2014 at 0:21
  • The other two exit relays are just intermediary nodes. This has nothing to do with the fact that wget is only using the first node in the circuit.
    – hmj6jmh
    Aug 1, 2014 at 0:45
  • No, torify wget is NOT using the first node in the circuit. You can see what you're connecting directly to with netstat or iftop. If torify wget IS showing an IP that you see with netstat or iftop, you have in fact IDed a huge bug in Tor. But I'm like 99.999% sure that you haven't.
    – mirimir
    Aug 1, 2014 at 0:57
  • How are you concluding that when wget is getting the IP of the first node consistently? That means the first node is relaying traffic directly to the destination and not through the next node in the circuit.
    – hmj6jmh
    Aug 1, 2014 at 2:53
  • You keep saying that, but this is the Tor log line that you've quoted: "Jul 29 06:37:47.000 [info] const node_t *choose_good_exit_server_general(int, int)(): Chose exit server '$2248CFE8C6E414D580C9C600EB16239EABE6E330=Paul20666RO at'" It says exit server, right? And that is what torify wget is using, right?
    – mirimir
    Aug 1, 2014 at 3:55

Answer to question 1 -- part 2 (but NOT question 2):

OK, I finally found the ultimate tool for analyzing the tor circuit--arm. I'm really surprised and disappointed that no one here pointed to this useful tool. It would have saved a lot of time on my part and mirimir's. This tool shows exactly what I wanted to know. Tor actually creates multiple circuits and distributes the bandwidth among them. I always thought it only created one circuit at a time. How come no one pointed this out?

wget is using one of 4 circuits:

$ torify wget -qO- http://ipecho.net/plain ; echo


The torified browser is using another:


browser arm

It should be noted that only these 2 circuits get reported to the tor log.

So mirimir's guess was right though, unfortunately, he provided no evidence.

Upon examining in detail the Tor Path Specification document, I found the following:

Building circuits

  • Clients build circuits preemptively
    • When running as a client, Tor tries to maintain at least a certain number of clean circuits, so that new streams can be handled quickly
    • On startup Tor tries to maintain one clean fast exit circuit that allows connections to port 80, and at least two fast clean stable internal circuits in case we get a resolve request or hidden service request
      • After that, Tor will adapt the circuits that it preemptively builds based on the requests it sees from the user: it tries to have two fast clean exit circuits available for every port seen within the past hour
  • Path selection and constraints
    • We choose the path for each new circuit before we build it
      • We choose the exit node first, followed by the other nodes in the circuit
    • If we're using Guard nodes, the first node must be a Guard
    • For "fast" circuits, we only choose nodes with the Fast flag
    • For all circuits, we weight node selection according to router bandwidth
    • We also weight the bandwidth of Exit and Guard flagged nodes depending on the fraction of total bandwidth that they make up and depending upon the position they are being selected for

So that explains the multiple circuits and that, therefore, wget is being routed to a different circuit than the one the browser gets routed to, and not to the first node in a single circuit like I surmised. But it doesn't explain why. Speculation--maybe it has to do with bandwidth load balancing?

In any case, question 2 remains open:

How can I get the EXIT node from bash?

By exit node, I mean the one that the browser sees.

  • Your bash commands are reporting the exit node for the circuits that they're using.
    – mirimir
    Aug 4, 2014 at 18:06

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .