@rynn-k/proxy-agent
v1.1.0
Published
Efficient proxy rotation agent for Node.js with seamless axios integration
Maintainers
Readme
@rynn-k/proxy-agent
Efficient proxy rotation agent for Node.js with seamless axios integration. Supports HTTP, HTTPS, SOCKS4, and SOCKS5 proxies with both authenticated and non-authenticated modes, automatic rotation, health checking, and comprehensive error handling.
🚀 Features
- ✅ Smart Proxy Rotation - Sequential or random proxy selection
- ✅ Multiple Protocol Support - HTTP, HTTPS, SOCKS4, and SOCKS5
- ✅ Multiple Auth Types - Support for authenticated and non-authenticated proxies
- ✅ Axios Integration - Drop-in replacement for axios HTTP/HTTPS agents
- ✅ Auto Validation - Built-in IP and port validation
- ✅ Health Checking - Test proxy connectivity and response times
- ✅ Auto Reload - Dynamic proxy file reloading
- ✅ Multiple Formats - Flexible proxy file format support (URL and colon-separated)
- ✅ TypeScript Ready - Full TypeScript definitions included
- ✅ Minimal Dependencies - Only requires proxy agent libraries
📦 Installation
npm install @rynn-k/proxy-agentAll required dependencies (https-proxy-agent, http-proxy-agent, socks-proxy-agent) will be installed automatically.
🔧 Quick Start
1. Create Proxy File
Create proxies.txt with your proxy list:
# HTTP/HTTPS proxies (ip:port)
192.168.1.1:8080
10.0.0.1:3128
# SOCKS5 proxies (URL format)
socks5://192.168.1.10:1080
socks5://username:[email protected]:1080
# SOCKS4 proxies
socks4://192.168.1.11:1080
# Authenticated HTTP proxies (ip:port:username:password)
192.168.1.2:8080:user123:pass456
proxy.example.com:3128:myuser:mypass
# Protocol-specific colon format (protocol:ip:port)
http:192.168.1.3:8080
https:secure-proxy.com:8080
socks5:192.168.1.4:1080
# Authenticated with protocol (protocol:ip:port:username:password)
http:192.168.1.5:8080:user:pass
socks5:192.168.1.6:1080:user:pass2. Basic Usage
const ProxyAgent = require('@rynn-k/proxy-agent');
const axios = require('axios');
// Initialize proxy agent
const proxy = new ProxyAgent('./proxies.txt');
// Use with axios
const response = await axios.get('https://httpbin.org/ip', proxy.config());
console.log('Your IP:', response.data.origin);3. Advanced Configuration
const proxy = new ProxyAgent('./proxies.txt', {
random: true, // Random proxy selection (default: false)
log: true, // Enable logging (default: true)
autoReload: true, // Auto-reload on file change (default: false)
encoding: 'utf-8', // File encoding (default: 'utf-8')
type: 'socks5' // Default proxy type when not specified (default: 'http')
});📖 API Documentation
Constructor
new ProxyAgent(proxyFilePath, options)Parameters:
proxyFilePath(string): Path to proxy file (default: 'proxies.txt')options(object): Configuration options
Options:
random(boolean): Use random proxy selection instead of sequentiallog(boolean): Enable/disable loggingautoReload(boolean): Auto-reload proxy file on changesencoding(string): File encoding for reading proxy filetype(string): Default proxy type ('http', 'https', 'socks4', 'socks5') when not specified in proxy string
Methods
config()
Returns axios configuration object with proxy agents configured.
const response = await axios.get('https://example.com', proxy.config());https()
Returns HTTPS proxy agent (or SOCKS agent for SOCKS proxies).
const httpsAgent = proxy.https();
const response = await axios.get('https://example.com', { httpsAgent, proxy: false });http()
Returns HTTP proxy agent (or SOCKS agent for SOCKS proxies).
const httpAgent = proxy.http();getCurrentProxy()
Get information about the currently selected proxy.
const current = proxy.getCurrentProxy();
console.log(current);
// { ip: '192.168.1.1', port: 8080, hasAuth: false, protocol: 'http', index: 0 }test(testUrl, timeout, useCurrentProxy)
Test proxy connectivity and measure response time.
const result = await proxy.test('https://httpbin.org/ip', 10000);
console.log(result);
// { success: true, proxy: 'socks5://192.168.1.10:1080', time: 245, data: {...} }Parameters:
testUrl(string): URL to test (default: 'https://httpbin.org/ip')timeout(number): Request timeout in milliseconds (default: 10000)useCurrentProxy(boolean): Use current proxy or get next (default: true)
list()
Get information about all loaded proxies.
const proxies = proxy.list();
console.log(proxies);
// [
// { index: 0, ip: '192.168.1.1', port: 8080, hasAuth: false, protocol: 'http', current: true },
// { index: 1, ip: '192.168.1.10', port: 1080, hasAuth: true, protocol: 'socks5', current: false }
// ]stats()
Get proxy agent statistics including protocol distribution.
const stats = proxy.stats();
console.log(stats);
// {
// total: 10,
// auth: 5,
// noAuth: 5,
// protocols: { http: 4, https: 2, socks5: 3, socks4: 1 },
// currentIndex: 2,
// lastUsedIndex: 1,
// random: false,
// file: '/path/to/proxies.txt',
// autoReload: false,
// currentProxy: { ip: '192.168.1.1', port: 8080, hasAuth: false, protocol: 'http', index: 1 }
// }reload()
Manually reload proxies from file.
proxy.reload();destroy()
Clean up resources and stop file watching.
proxy.destroy();💡 Usage Examples
Basic Rotation with SOCKS5
const ProxyAgent = require('@rynn-k/proxy-agent');
const axios = require('axios');
// Create proxies.txt with SOCKS5 proxies
// socks5://192.168.1.10:1080
// socks5://user:[email protected]:1080
const proxy = new ProxyAgent('./proxies.txt');
// Each request uses the next proxy in rotation
for (let i = 0; i < 5; i++) {
try {
const response = await axios.get('https://httpbin.org/ip', proxy.config());
console.log(`Request ${i + 1}:`, response.data.origin);
} catch (error) {
console.error(`Request ${i + 1} failed:`, error.message);
}
}Mixed Protocol Proxies
// proxies.txt contains mixed protocols:
// http://192.168.1.1:8080
// socks5://192.168.1.10:1080
// socks4://192.168.1.11:1080
// https://secure.proxy.com:8080
const proxy = new ProxyAgent('./proxies.txt', {
random: true, // Randomly select from all protocols
log: true
});
// The agent automatically uses the correct protocol for each proxy
const response = await axios.get('https://api.example.com/data', proxy.config());Default Protocol Configuration
// If your proxies.txt doesn't specify protocols:
// 192.168.1.10:1080
// 192.168.1.11:1080
// 192.168.1.12:1080:user:pass
// Set default protocol to SOCKS5
const proxy = new ProxyAgent('./proxies.txt', {
type: 'socks5', // All proxies without protocol will be treated as SOCKS5
log: true
});
const response = await axios.get('https://example.com', proxy.config());Error Handling & Retry with Protocol Fallback
async function robustRequest(url, maxRetries = 3) {
for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
const response = await axios.get(url, {
...proxy.config(),
timeout: 10000
});
const currentProxy = proxy.getCurrentProxy();
console.log(`✅ Success with ${currentProxy.protocol}://${currentProxy.ip}:${currentProxy.port}`);
return response.data;
} catch (error) {
const currentProxy = proxy.getCurrentProxy();
console.log(`❌ Attempt ${attempt} failed with ${currentProxy.protocol}://${currentProxy.ip}:${currentProxy.port}`);
if (attempt === maxRetries) {
throw new Error(`All ${maxRetries} attempts failed`);
}
// Wait before retry with different proxy
await new Promise(resolve => setTimeout(resolve, 2000));
}
}
}
// Usage
try {
const data = await robustRequest('https://api.example.com/data');
console.log(data);
} catch (error) {
console.error('Request failed after all retries:', error.message);
}Axios Instance Integration
const axiosWithProxy = axios.create({
timeout: 15000,
headers: {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
}
});
// Add proxy rotation to every request
axiosWithProxy.interceptors.request.use(config => {
const proxyConfig = proxy.config();
config.httpsAgent = proxyConfig.httpsAgent;
config.httpAgent = proxyConfig.httpAgent;
config.proxy = false;
return config;
});
// Now all requests automatically use rotating proxies
const response = await axiosWithProxy.get('https://api.example.com/data');Health Checking All Protocols
// Test all proxies and filter working ones
const proxy = new ProxyAgent('./proxies.txt', { log: false });
const workingProxies = [];
const failedProxies = [];
const allProxies = proxy.list();
for (let i = 0; i < allProxies.length; i++) {
const proxyInfo = allProxies[i];
try {
const result = await proxy.test('https://httpbin.org/ip', 10000, false);
if (result.success) {
workingProxies.push({
...proxyInfo,
responseTime: result.time
});
console.log(`✅ ${proxyInfo.protocol}://${proxyInfo.ip}:${proxyInfo.port} - ${result.time}ms`);
} else {
failedProxies.push(proxyInfo);
console.log(`❌ ${proxyInfo.protocol}://${proxyInfo.ip}:${proxyInfo.port} - ${result.error}`);
}
} catch (error) {
failedProxies.push(proxyInfo);
console.log(`❌ ${proxyInfo.protocol}://${proxyInfo.ip}:${proxyInfo.port} - ${error.message}`);
}
}
console.log(`\n📊 Results:`);
console.log(` Working: ${workingProxies.length}`);
console.log(` Failed: ${failedProxies.length}`);
// Sort by response time
workingProxies.sort((a, b) => a.responseTime - b.responseTime);
console.log('\n⚡ Fastest proxies:');
workingProxies.slice(0, 3).forEach(p => {
console.log(` ${p.protocol}://${p.ip}:${p.port} - ${p.responseTime}ms`);
});Protocol-Specific Usage
// Use only SOCKS5 proxies for specific tasks
const socksProxy = new ProxyAgent('./socks5-proxies.txt', {
type: 'socks5'
});
// Use only HTTP proxies for other tasks
const httpProxy = new ProxyAgent('./http-proxies.txt', {
type: 'http'
});
// Different requests with different proxy types
const socksResponse = await axios.get('https://api1.example.com', socksProxy.config());
const httpResponse = await axios.get('https://api2.example.com', httpProxy.config());🔧 Proxy File Formats
The library supports multiple proxy formats:
URL Format (Recommended)
# HTTP/HTTPS
http://192.168.1.1:8080
https://secure-proxy.com:8080
http://username:[email protected]:8080
# SOCKS5
socks5://192.168.1.10:1080
socks5://username:[email protected]:1080
# SOCKS4
socks4://192.168.1.12:1080Colon-Separated Format
# Basic format (ip:port) - uses default type from options
192.168.1.1:8080
proxy.example.com:3128
# With protocol (protocol:ip:port)
http:192.168.1.1:8080
socks5:192.168.1.10:1080
socks4:192.168.1.11:1080
# With authentication (ip:port:username:password)
192.168.1.2:8080:user123:password123
proxy.example.com:3128:myuser:mypass
# With protocol and authentication (protocol:ip:port:username:password)
http:192.168.1.3:8080:user:pass
socks5:192.168.1.10:1080:user:passComments and Empty Lines
# This is a comment
192.168.1.1:8080
# Empty lines are ignored
socks5://192.168.1.10:1080 # Inline comments are not supported🔍 Protocol Support Details
| Protocol | Authentication | URL Format | Colon Format | |----------|---------------|------------|--------------| | HTTP | ✅ Yes | ✅ Yes | ✅ Yes | | HTTPS | ✅ Yes | ✅ Yes | ✅ Yes | | SOCKS5 | ✅ Yes | ✅ Yes | ✅ Yes | | SOCKS4 | ❌ No | ✅ Yes | ✅ Yes |
Note: SOCKS4 protocol does not support authentication. If you specify credentials with SOCKS4, they will be ignored.
📊 Statistics and Monitoring
const proxy = new ProxyAgent('./proxies.txt');
// Get detailed statistics
const stats = proxy.stats();
console.log('Total proxies:', stats.total);
console.log('Authenticated:', stats.auth);
console.log('Protocol distribution:', stats.protocols);
// Output: { http: 5, https: 3, socks5: 8, socks4: 2 }
// Monitor current proxy
setInterval(() => {
const current = proxy.getCurrentProxy();
if (current) {
console.log(`Currently using: ${current.protocol}://${current.ip}:${current.port}`);
}
}, 5000);⚙️ TypeScript Support
Full TypeScript definitions are included:
import ProxyAgent from '@rynn-k/proxy-agent';
const proxy = new ProxyAgent('./proxies.txt', {
random: true,
type: 'socks5'
});
// Type-safe proxy info
const info: ProxyAgent.CurrentProxyInfo | null = proxy.getCurrentProxy();
// Type-safe stats
const stats: ProxyAgent.ProxyStats = proxy.stats();🐛 Troubleshooting
SOCKS proxies not working
Make sure the module is properly installed with all dependencies:
npm install @rynn-k/proxy-agentAuthentication issues with SOCKS4
SOCKS4 does not support authentication. Use SOCKS5 instead:
# Change from
socks4://user:[email protected]:1080
# To
socks5://user:[email protected]:1080Mixed protocol errors
Ensure each proxy line specifies the correct protocol or set a default type:
const proxy = new ProxyAgent('./proxies.txt', {
type: 'http' // Default for lines without protocol
});📝 License
MIT
