
Biblioteca Python para gerenciamento programático de instâncias Tor com proxy SOCKS5, rotação de identidade, isolamento de fluxo, serviços ocultos, controle de circuito e clientes HTTP assíncronos.
Biblioteca Python para gerenciar instâncias Tor programaticamente.
Linux (Debian/Ubuntu):
sudo apt-get install tor obfs4proxy
Windows:
Baixe o Tor Expert Bundle em torproject.org.
pip install xtor
# ou
uv add xtor
from xtor import Tor
with Tor.start(port=9052, control_port=9053, host="127.0.0.1") as tor:
print(f"Conectado através do IP: {tor.ip}")
resp = tor.client.get("https://api.ipify.org")
print(resp.text)
from xtor import Tor
from xtor.exceptions import TorNotFoundError, PortInUseError
try:
with Tor.start(port=9052, control_port=9053, host="127.0.0.1", password="minhasenha") as tor:
print(tor.ip)
resp = tor.client.get("https://api.ipify.org")
print(resp.text)
except TorNotFoundError:
print("Tor não encontrado no PATH")
except PortInUseError as e:
print(f"Porta em uso: {e}")
Nota:
Tor.startTor()está disponível como um alias paraTor.start()para compatibilidade com versões anteriores.
with Tor(password="minhasenha", port=9050, control_port=9051) as tor:
print(tor.ip)
with Tor.start(port=9052, control_port=9053, host="127.0.0.1") as tor:
print(tor.ip)
tor.new_identity(wait=True, timeout=30)
print(tor.ip) # Novo IP
import asyncio
from xtor import Tor
async def main():
with Tor.start(port=9052, control_port=9053, host="127.0.0.1") as tor:
async with tor.async_client as client:
resp = await client.get("https://api.ipify.org")
print(resp.text)
asyncio.run(main())
with Tor.start(port=9052, control_port=9053, host="127.0.0.1") as tor:
# Cada chave recebe seu próprio circuito
client_a = tor.isolated_client("sessao-a")
client_b = tor.isolated_client("sessao-b")
# Requisições através de client_a e client_b usam circuitos diferentes
with Tor.start(port=9052, control_port=9053, host="127.0.0.1") as tor:
circuits = tor.get_circuits()
for c in circuits:
print(f"Circuito {c.id}: {c.status}, caminho: {c.path}")
# Fechar um circuito específico
tor.close_circuit(circuits[0].id)
with Tor.start(port=9052, control_port=9053, host="127.0.0.1") as tor:
info = tor.exit_node
if info:
print(f"Saída: {info.nickname} ({info.country})")
print(f"Flags: {info.flags}")
with Tor.start(port=9052, control_port=9053, host="127.0.0.1") as tor:
service = tor.create_hidden_service({80: 8080})
print(f"Serviço: {service.onion_address}")
# Remover quando terminar
tor.remove_hidden_service(service)
with Tor.start(port=9052, control_port=9053, host="127.0.0.1") as tor:
def on_bandwidth(event):
print(f"Lido: {event.read}, Escrito: {event.written}")
tor.add_event_listener("BW", on_bandwidth)
# ... realizar trabalho ...
tor.remove_event_listener(on_bandwidth)
from xtor import TorPool
with TorPool(size=3, base_port=9100, password="secret") as pool:
# Round-robin
tor = pool.next()
print(tor.client.get("https://api.ipify.org").text)
# Rotacionar todas as identidades
pool.rotate_all()
# Seleção aleatória
tor = pool.random()
from xtor import Tor
# Iniciar instância nomeada
tor = Tor.start(port=9052, control_port=9053, host="127.0.0.1", name="meu-tor")
# Depois, reconectar pelo nome
tor = Tor.from_name("meu-tor")
with tor:
print(tor.ip)
A CLI xtor gerencia instâncias Tor nomeadas como processos em segundo plano.
# Iniciar uma instância nomeada
xtor start meu-tor --port 9052 --control-port 9053
# Listar instâncias
xtor list
# Detalhes da conexão
xtor connect meu-tor
# Parar instância
xtor stop meu-tor
# Remover instância e dados
xtor remove meu-tor
XtorError (base)
├── TorNotFoundError
├── PortInUseError
├── IdentityChangeTimeout
├── ConnectionError
└── AuthenticationError
Padrão para capturar todas:
from xtor.exceptions import XtorError
try:
with Tor.start(port=9052, control_port=9053, host="127.0.0.1") as tor:
...
except XtorError as e:
print(f"Erro xtor: {e}")