What is IP Masking?
IP masking (also called IP hiding or IP spoofing) is the practice of concealing your true IP address by routing your internet traffic through an intermediary server. This protects your privacy, bypasses geo-restrictions, prevents tracking, and is essential for web scraping, security testing, and maintaining anonymity online.
How IP Masking Works
Basic Mechanism
Normal Connection:
Your Device (IP: 203.0.113.45) → Website
Website sees: 203.0.113.45
With IP Masking:
Your Device (IP: 203.0.113.45) → Proxy (IP: 198.51.100.10) → Website
Website sees: 198.51.100.10 (proxy IP)
IP Masking Methods
interface IPMaskingMethods {
proxy: {
type: 'HTTP/HTTPS/SOCKS proxy server';
anonymity: 'Varies (transparent to elite)';
speed: 'Fast';
setup: 'Easy';
cost: 'Free to $50+/month';
useCases: ['Web scraping', 'API requests', 'Automation'];
};
vpn: {
type: 'Virtual Private Network';
anonymity: 'High (encrypted tunnel)';
speed: 'Medium (encryption overhead)';
setup: 'Very easy (apps)';
cost: '$5-15/month';
useCases: ['General browsing', 'Geo-unblocking', 'Privacy'];
};
tor: {
type: 'The Onion Router (multi-hop)';
anonymity: 'Very high (3+ hops)';
speed: 'Slow';
setup: 'Easy (Tor Browser)';
cost: 'Free';
useCases: ['Maximum anonymity', 'Whistleblowing', 'Censorship bypass'];
};
ssh: {
type: 'SSH tunnel (SOCKS proxy)';
anonymity: 'Medium to high';
speed: 'Fast';
setup: 'Technical';
cost: 'VPS cost ($5+/month)';
useCases: ['Development', 'Secure remote access'];
};
cloudflare: {
type: 'Cloudflare WARP/1.1.1.1';
anonymity: 'Medium (DNS + encrypted)';
speed: 'Very fast';
setup: 'Very easy (app)';
cost: 'Free';
useCases: ['DNS privacy', 'Basic security'];
};
}
IP Masking with HTTP Proxies
Proxy Implementation
interface ProxyConfig {
host: string;
port: number;
username?: string;
password?: string;
type: 'http' | 'https' | 'socks4' | 'socks5';
}
class IPMasker {
async fetchWithProxy(url: string, proxy: ProxyConfig): Promise<Response> {
// Using CORS proxy service
const response = await fetch(
`https://corsproxy.io/?url=${encodeURIComponent(url)}`,
{
headers: {
'x-cors-api-key': 'your-api-key'
}
}
);
return response;
}
async fetchDirectProxy(url: string, proxy: ProxyConfig): Promise<Response> {
// Node.js with proxy (using https-proxy-agent)
const { HttpsProxyAgent } = await import('https-proxy-agent');
const proxyUrl = proxy.username
? `http://${proxy.username}:${proxy.password}@${proxy.host}:${proxy.port}`
: `http://${proxy.host}:${proxy.port}`;
const agent = new HttpsProxyAgent(proxyUrl);
const response = await fetch(url, {
// @ts-ignore
agent
});
return response;
}
async checkIP(): Promise<string> {
const response = await fetch('https://api.ipify.org?format=json');
const data = await response.json();
return data.ip;
}
async verifyIPMasking(proxy: ProxyConfig): Promise<{
original: string;
masked: string;
success: boolean;
}> {
// Check original IP
const originalIP = await this.checkIP();
// Check IP through proxy
const maskedResponse = await this.fetchWithProxy('https://api.ipify.org?format=json', proxy);
const maskedData = await maskedResponse.json();
const maskedIP = maskedData.ip;
return {
original: originalIP,
masked: maskedIP,
success: originalIP !== maskedIP
};
}
}
// Usage
const masker = new IPMasker();
const proxy: ProxyConfig = {
host: 'proxy.example.com',
port: 8080,
username: 'user',
password: 'pass',
type: 'http'
};
// Verify IP is masked
const verification = await masker.verifyIPMasking(proxy);
console.log('Original IP:', verification.original);
console.log('Masked IP:', verification.masked);
console.log('Masking successful:', verification.success);
Rotating IP Addresses
Automatic IP Rotation
interface RotatingProxyConfig {
proxies: ProxyConfig[];
strategy: 'round-robin' | 'random' | 'least-used';
rotateInterval?: number; // milliseconds
}
class RotatingIPMasker {
private proxies: ProxyConfig[];
private currentIndex: number = 0;
private requestCounts: Map<string, number> = new Map();
private strategy: RotatingProxyConfig['strategy'];
constructor(config: RotatingProxyConfig) {
this.proxies = config.proxies;
this.strategy = config.strategy;
// Initialize request counts
config.proxies.forEach(proxy => {
this.requestCounts.set(`${proxy.host}:${proxy.port}`, 0);
});
}
getNextProxy(): ProxyConfig {
let proxy: ProxyConfig;
switch (this.strategy) {
case 'round-robin':
proxy = this.proxies[this.currentIndex];
this.currentIndex = (this.currentIndex + 1) % this.proxies.length;
break;
case 'random':
const randomIndex = Math.floor(Math.random() * this.proxies.length);
proxy = this.proxies[randomIndex];
break;
case 'least-used':
proxy = this.getLeastUsedProxy();
break;
default:
proxy = this.proxies[0];
}
// Increment request count
const key = `${proxy.host}:${proxy.port}`;
this.requestCounts.set(key, (this.requestCounts.get(key) || 0) + 1);
return proxy;
}
private getLeastUsedProxy(): ProxyConfig {
let minCount = Infinity;
let leastUsedProxy = this.proxies[0];
for (const proxy of this.proxies) {
const key = `${proxy.host}:${proxy.port}`;
const count = this.requestCounts.get(key) || 0;
if (count < minCount) {
minCount = count;
leastUsedProxy = proxy;
}
}
return leastUsedProxy;
}
async fetchWithRotation(url: string): Promise<Response> {
const proxy = this.getNextProxy();
console.log(`Using proxy: ${proxy.host}:${proxy.port}`);
const response = await fetch(
`https://corsproxy.io/?url=${encodeURIComponent(url)}`,
{
headers: {
'x-cors-api-key': 'your-api-key'
}
}
);
return response;
}
async scrapeMultiplePages(urls: string[]): Promise<any[]> {
const results = [];
for (const url of urls) {
const proxy = this.getNextProxy();
console.log(`Scraping ${url} via ${proxy.host}:${proxy.port}`);
const response = await this.fetchWithRotation(url);
const data = await response.text();
results.push({
url,
proxy: `${proxy.host}:${proxy.port}`,
success: response.ok,
data
});
// Delay between requests
await this.delay(1000 + Math.random() * 2000);
}
return results;
}
private delay(ms: number): Promise<void> {
return new Promise(resolve => setTimeout(resolve, ms));
}
getStats(): Record<string, number> {
const stats: Record<string, number> = {};
this.requestCounts.forEach((count, key) => {
stats[key] = count;
});
return stats;
}
}
// Usage
const rotatingMasker = new RotatingIPMasker({
proxies: [
{ host: 'proxy1.example.com', port: 8080, type: 'http' },
{ host: 'proxy2.example.com', port: 8080, type: 'http' },
{ host: 'proxy3.example.com', port: 8080, type: 'http' }
],
strategy: 'round-robin'
});
// Scrape with rotating IPs
const urls = [
'https://example.com/page1',
'https://example.com/page2',
'https://example.com/page3',
'https://example.com/page4',
'https://example.com/page5'
];
const results = await rotatingMasker.scrapeMultiplePages(urls);
console.log('Request distribution:', rotatingMasker.getStats());
Geographic IP Masking
Geo-Specific Proxies
interface GeoProxy {
country: string;
city: string;
proxy: ProxyConfig;
}
class GeoIPMasker {
private geoProxies: Map<string, GeoProxy[]> = new Map();
addGeoProxy(geoProxy: GeoProxy): void {
const country = geoProxy.country.toLowerCase();
if (!this.geoProxies.has(country)) {
this.geoProxies.set(country, []);
}
this.geoProxies.get(country)!.push(geoProxy);
}
getProxyForCountry(country: string): ProxyConfig {
const countryKey = country.toLowerCase();
const proxies = this.geoProxies.get(countryKey);
if (!proxies || proxies.length === 0) {
throw new Error(`No proxies available for country: ${country}`);
}
// Random proxy from country
const randomProxy = proxies[Math.floor(Math.random() * proxies.length)];
return randomProxy.proxy;
}
async fetchFromCountry(url: string, country: string): Promise<Response> {
const proxy = this.getProxyForCountry(country);
console.log(`Fetching from ${country} via ${proxy.host}:${proxy.port}`);
const response = await fetch(
`https://corsproxy.io/?url=${encodeURIComponent(url)}`,
{
headers: {
'x-cors-api-key': 'your-api-key'
}
}
);
return response;
}
async scrapeFromMultipleCountries(url: string, countries: string[]): Promise<any[]> {
const results = [];
for (const country of countries) {
try {
const response = await this.fetchFromCountry(url, country);
const data = await response.text();
results.push({
country,
url,
success: true,
data
});
} catch (error) {
results.push({
country,
url,
success: false,
error: (error as Error).message
});
}
await this.delay(2000); // Delay between countries
}
return results;
}
private delay(ms: number): Promise<void> {
return new Promise(resolve => setTimeout(resolve, ms));
}
getAvailableCountries(): string[] {
return Array.from(this.geoProxies.keys());
}
}
// Usage
const geoMasker = new GeoIPMasker();
// Add geo-specific proxies
geoMasker.addGeoProxy({
country: 'US',
city: 'New York',
proxy: { host: 'us-ny-proxy.example.com', port: 8080, type: 'http' }
});
geoMasker.addGeoProxy({
country: 'UK',
city: 'London',
proxy: { host: 'uk-london-proxy.example.com', port: 8080, type: 'http' }
});
geoMasker.addGeoProxy({
country: 'JP',
city: 'Tokyo',
proxy: { host: 'jp-tokyo-proxy.example.com', port: 8080, type: 'http' }
});
// Scrape from multiple countries
const results = await geoMasker.scrapeFromMultipleCountries(
'https://www.example.com',
['US', 'UK', 'JP']
);
console.log('Results from different countries:', results);
IP Leak Prevention
Comprehensive Protection
interface IPLeakProtection {
webrtc: {
risk: 'WebRTC can leak real IP even with VPN/proxy';
prevention: 'Disable WebRTC or use leak-proof browsers';
detection: 'Check https://browserleaks.com/webrtc';
};
dns: {
risk: 'DNS queries may use ISP DNS, leaking activity';
prevention: 'Use VPN DNS or encrypted DNS (DoH/DoT)';
detection: 'Check https://dnsleaktest.com';
};
ipv6: {
risk: 'IPv6 may bypass IPv4 proxy/VPN';
prevention: 'Disable IPv6 or use IPv6-aware proxy';
detection: 'Check https://test-ipv6.com';
};
headers: {
risk: 'X-Forwarded-For, Via headers can expose real IP';
prevention: 'Use elite proxy that strips headers';
detection: 'Check response headers';
};
}
class LeakProofIPMasker {
async fetchWithLeakProtection(url: string, apiKey: string): Promise<Response> {
const response = await fetch(
`https://corsproxy.io/?url=${encodeURIComponent(url)}`,
{
headers: {
'x-cors-api-key': apiKey,
// Don't send potentially identifying headers
'X-Forwarded-For': undefined,
'Via': undefined,
'X-Real-IP': undefined
}
}
);
return response;
}
async checkForLeaks(): Promise<{
publicIP: string;
dnsLeak: boolean;
webrtcLeak: boolean;
ipv6Leak: boolean;
}> {
// Check public IP
const ipResponse = await fetch('https://api.ipify.org?format=json');
const { ip: publicIP } = await ipResponse.json();
return {
publicIP,
dnsLeak: false, // Would need actual DNS leak test
webrtcLeak: false, // Would need WebRTC check
ipv6Leak: false // Would need IPv6 check
};
}
}
Residential vs Datacenter IP Masking
IP Type Comparison
interface IPTypes {
datacenter: {
source: 'Server hosting providers (AWS, DigitalOcean, etc.)';
detection: 'Easy to detect (ASN databases)';
speed: 'Very fast';
cost: '$1-5/GB';
trust: 'Low (frequently blocked)';
useCases: ['High-volume scraping', 'API requests', 'Testing'];
};
residential: {
source: 'Real ISP-assigned home IPs';
detection: 'Very hard to detect';
speed: 'Medium (depends on homeowner connection)';
cost: '$5-15/GB';
trust: 'High (looks like real user)';
useCases: ['Sneaker bots', 'Social media', 'Account creation'];
};
mobile: {
source: 'Mobile carrier IPs (4G/LTE)';
detection: 'Very hard to detect';
speed: 'Medium to slow';
cost: '$10-25/GB';
trust: 'Very high (mobile = human)';
useCases: ['Mobile app testing', 'Instagram', 'App scraping'];
};
}
VPN for IP Masking
VPN vs Proxy
interface VPNvsProxy {
vpn: {
encryption: 'Full traffic encrypted';
scope: 'All device traffic routed';
setup: 'System-wide or per-app';
speed: 'Medium (encryption overhead)';
anonymity: 'High';
cost: '$5-15/month';
detection: 'Medium (VPN IP ranges known)';
};
proxy: {
encryption: 'HTTPS proxies only';
scope: 'Per-application basis';
setup: 'Configure per app/script';
speed: 'Fast';
anonymity: 'Medium to high';
cost: '$0-50+/month';
detection: 'Varies by proxy type';
};
}
// VPN-like functionality with SOCKS5
async function fetchViaSocks5(url: string) {
const { SocksProxyAgent } = await import('socks-proxy-agent');
const agent = new SocksProxyAgent('socks5://username:password@proxy.example.com:1080');
const response = await fetch(url, {
// @ts-ignore
agent
});
return response;
}
Best Practices
Effective IP Masking
interface IPMaskingBestPractices {
selection: {
rule: 'Choose appropriate IP type for use case';
reason: 'Datacenter IPs get blocked on many sites';
example: 'Residential for e-commerce, datacenter for APIs';
};
rotation: {
rule: 'Rotate IPs regularly';
reason: 'Same IP for too long triggers detection';
example: 'New IP every 100 requests or 10 minutes';
};
consistency: {
rule: 'Keep same IP for related requests';
reason: 'IP change mid-session is suspicious';
example: 'Login + browse + checkout = same IP';
};
geolocation: {
rule: 'Match IP location with target audience';
reason: 'Wrong location triggers fraud checks';
example: 'US IP for US site, UK IP for UK site';
};
leakPrevention: {
rule: 'Test for WebRTC/DNS/IPv6 leaks';
reason: 'Leaks expose real IP';
tools: ['browserleaks.com', 'ipleak.net', 'dnsleaktest.com'];
};
combination: {
rule: 'Combine IP masking with fingerprint spoofing';
reason: 'IP alone is not enough for anonymity';
example: 'Proxy + user agent rotation + canvas spoofing';
};
}
Testing IP Masking
Verification Tools
class IPMaskingTester {
async testIPMasking(): Promise<{
realIP: string;
maskedIP: string;
location: any;
leaks: string[];
}> {
// Check current IP
const ipResponse = await fetch('https://api.ipify.org?format=json');
const { ip: currentIP } = await ipResponse.json();
// Get IP geolocation
const geoResponse = await fetch(`https://ipapi.co/${currentIP}/json/`);
const location = await geoResponse.json();
const leaks: string[] = [];
// Check for common leaks
// (In real implementation, would check WebRTC, DNS, etc.)
return {
realIP: currentIP,
maskedIP: currentIP,
location,
leaks
};
}
async compareWithAndWithoutMasking(url: string): Promise<{
without: string;
with: string;
masked: boolean;
}> {
// Request without proxy
const response1 = await fetch(url);
const data1 = await response1.text();
// Request with proxy
const response2 = await fetch(
`https://corsproxy.io/?url=${encodeURIComponent(url)}`,
{
headers: {
'x-cors-api-key': 'your-api-key'
}
}
);
const data2 = await response2.text();
// Check if IPs differ (simplified check)
const masked = data1 !== data2;
return {
without: data1.substring(0, 100),
with: data2.substring(0, 100),
masked
};
}
}
// Usage
const tester = new IPMaskingTester();
const result = await tester.testIPMasking();
console.log('IP masking test:', result);