On this page

Extends: undici.Dispatcher

A SOCKS5 proxy wrapper class that implements the Dispatcher API. It enables HTTP requests to be routed through a SOCKS5 proxy server, providing connection tunneling and authentication support.

new Socks5ProxyAgent(proxyUrl, options?): void

Arguments:

  • proxyUrl string | URL (required) - The SOCKS5 proxy server URL. Must use socks5:// or socks:// protocol.
  • options Socks5ProxyAgent.Options (optional) - Additional configuration options.

Returns: Socks5ProxyAgent

Extends: PoolOptions

  • headers IncomingHttpHeaders (optional) - Additional headers to send with proxy connections.
  • username string (optional) - SOCKS5 proxy username for authentication. Can also be provided in the proxy URL.
  • password string (optional) - SOCKS5 proxy password for authentication. Can also be provided in the proxy URL.
  • connect Function (optional) - Custom connector function for the proxy connection.
  • proxyTls BuildOptions (optional) - TLS options for the proxy connection (when using SOCKS5 over TLS).
  • requestTls BuildOptions (optional) - TLS options applied to the HTTPS connection to the target server through the SOCKS5 tunnel. Use this to configure ca, cert, key, rejectUnauthorized, servername, etc. for the target HTTPS endpoint.

Examples:

import { Socks5ProxyAgent } from 'undici'

const socks5Proxy = new Socks5ProxyAgent('socks5://localhost:1080')
// or with authentication
const socks5ProxyWithAuth = new Socks5ProxyAgent('socks5://user:pass@localhost:1080')
// or with options
const socks5ProxyWithOptions = new Socks5ProxyAgent('socks5://localhost:1080', {
  username: 'user',
  password: 'pass',
  connections: 10
})

This will instantiate the Socks5ProxyAgent. It will not do anything until registered as the dispatcher to use with requests.

import { Socks5ProxyAgent } from 'undici'

const socks5Proxy = new Socks5ProxyAgent('socks5://localhost:1080')
import { setGlobalDispatcher, request, Socks5ProxyAgent } from 'undici'

const socks5Proxy = new Socks5ProxyAgent('socks5://localhost:1080')
setGlobalDispatcher(socks5Proxy)

const { statusCode, body } = await request('http://localhost:3000/foo')

console.log('response received', statusCode) // response received 200

for await (const data of body) {
  console.log('data', data.toString('utf8')) // data foo
}
import { Socks5ProxyAgent, request } from 'undici'

const socks5Proxy = new Socks5ProxyAgent('socks5://localhost:1080')

const {
  statusCode,
  body
} = await request('http://localhost:3000/foo', { dispatcher: socks5Proxy })

console.log('response received', statusCode) // response received 200

for await (const data of body) {
  console.log('data', data.toString('utf8')) // data foo
}
import { setGlobalDispatcher, request, Socks5ProxyAgent } from 'undici'

// Authentication via URL
const socks5Proxy = new Socks5ProxyAgent('socks5://username:password@localhost:1080')

// Or authentication via options
// const socks5Proxy = new Socks5ProxyAgent('socks5://localhost:1080', {
//   username: 'username',
//   password: 'password'
// })

setGlobalDispatcher(socks5Proxy)

const { statusCode, body } = await request('http://localhost:3000/foo')

console.log('response received', statusCode) // response received 200

for await (const data of body) {
  console.log('data', data.toString('utf8')) // data foo
}

SOCKS5 proxy supports both HTTP and HTTPS requests through tunneling:

import { Socks5ProxyAgent, request } from 'undici'

const socks5Proxy = new Socks5ProxyAgent('socks5://localhost:1080')

const response = await request('https://api.example.com/data', {
  dispatcher: socks5Proxy,
  method: 'GET'
})

console.log('Response status:', response.statusCode)
console.log('Response data:', await response.body.json())
import { Socks5ProxyAgent, fetch } from 'undici'

const socks5Proxy = new Socks5ProxyAgent('socks5://localhost:1080')

const response = await fetch('http://localhost:3000/api/users', {
  dispatcher: socks5Proxy,
  method: 'GET'
})

console.log('Response status:', response.status)
console.log('Response data:', await response.text())

SOCKS5ProxyWrapper automatically manages connection pooling for better performance:

import { Socks5ProxyAgent, request } from 'undici'

const socks5Proxy = new Socks5ProxyAgent('socks5://localhost:1080', {
  connections: 10, // Allow up to 10 concurrent connections
  pipelining: 1    // Enable HTTP/1.1 pipelining
})

// Multiple requests will reuse connections through the SOCKS5 tunnel
const responses = await Promise.all([
  request('http://api.example.com/endpoint1', { dispatcher: socks5Proxy }),
  request('http://api.example.com/endpoint2', { dispatcher: socks5Proxy }),
  request('http://api.example.com/endpoint3', { dispatcher: socks5Proxy })
])

console.log('All requests completed through the same SOCKS5 proxy')
Socks5ProxyAgent.close(): void

Closes the SOCKS5 proxy wrapper and waits for all underlying pools and connections to close before resolving.

Returns: Promise<void>

import { Socks5ProxyAgent, setGlobalDispatcher } from 'undici'

const socks5Proxy = new Socks5ProxyAgent('socks5://localhost:1080')
setGlobalDispatcher(socks5Proxy)

// ... make requests

await socks5Proxy.close()
Socks5ProxyAgent.destroy(err?): void

Destroys the SOCKS5 proxy wrapper and all underlying connections immediately.

Arguments:

  • err Error (optional) - The error that caused the destruction.

Returns: Promise<void>

import { Socks5ProxyAgent } from 'undici'

const socks5Proxy = new Socks5ProxyAgent('socks5://localhost:1080')

// Force close all connections
await socks5Proxy.destroy()
Socks5ProxyAgent.dispatch(options, handlers): void

Implements Dispatcher.dispatch(options, handlers).

Socks5ProxyAgent.request(options, callback?): void

See Dispatcher.request(options [, callback]).

SOCKS5 proxy connections can be debugged using Node.js diagnostics:

This will output detailed information about the SOCKS5 handshake, authentication, and connection establishment.

The Socks5ProxyAgent supports the following SOCKS5 features:

  • No Authentication (0x00) - For public or internal proxies
  • Username/Password (0x02) - RFC 1929 authentication
  • IPv4 (0x01) - Standard IPv4 addresses
  • Domain Name (0x03) - Domain names (recommended for flexibility)
  • IPv6 (0x04) - IPv6 addresses (full support for standard and compressed notation)
  • CONNECT (0x01) - Establish TCP connection (primary use case for HTTP)

The wrapper handles various SOCKS5 error conditions:

  • Connection refused by proxy
  • Authentication failures
  • Network unreachable
  • Host unreachable
  • Unsupported address types or commands
  • Connection Pooling: Automatically pools connections through the SOCKS5 tunnel for better performance
  • HTTP/1.1 Pipelining: Supports pipelining when enabled
  • DNS Resolution: Domain names are resolved by the SOCKS5 proxy, reducing local DNS queries
  • TLS Termination: HTTPS connections are encrypted end-to-end, with the SOCKS5 proxy only handling the TCP tunnel
  1. Authentication: Credentials are sent to the SOCKS5 proxy in plaintext unless using SOCKS5 over TLS
  2. DNS Leaks: All DNS resolution happens on the proxy server, preventing DNS leaks
  3. End-to-end Encryption: HTTPS traffic remains encrypted between client and final destination
  4. Connection Security: Consider using authenticated proxies and secure networks
  • Protocol: SOCKS5 (RFC 1928) with Username/Password Authentication (RFC 1929)
  • Transport: TCP only (UDP support not implemented)
  • Node.js: Compatible with all supported Node.js versions
  • HTTP Versions: Works with HTTP/1.1 and HTTP/2 over the tunnel