iploop 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (4) hide show
  1. package/README.md +76 -0
  2. package/index.d.ts +51 -0
  3. package/index.js +152 -0
  4. package/package.json +21 -0
package/README.md ADDED
@@ -0,0 +1,76 @@
1
+ # IPLoop Node.js SDK
2
+
3
+ Residential proxy SDK — route requests through millions of real devices across 111+ countries.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ npm install iploop
9
+ ```
10
+
11
+ ## Quick Start
12
+
13
+ ```javascript
14
+ const IPLoop = require('iploop');
15
+
16
+ const ip = new IPLoop('your-api-key');
17
+
18
+ // Fetch any URL through a residential proxy
19
+ const res = await ip.get('https://httpbin.org/ip');
20
+ console.log(res.body);
21
+
22
+ // Target a specific country
23
+ const de = await ip.get('https://example.com', { country: 'DE' });
24
+
25
+ // POST request
26
+ const post = await ip.post('https://api.example.com/data', {
27
+ body: JSON.stringify({ key: 'value' }),
28
+ headers: { 'Content-Type': 'application/json' }
29
+ });
30
+ ```
31
+
32
+ ## Sticky Sessions
33
+
34
+ Keep the same IP across multiple requests:
35
+
36
+ ```javascript
37
+ const session = ip.session({ country: 'US', city: 'newyork' });
38
+ const page1 = await session.get('https://site.com/page1'); // same IP
39
+ const page2 = await session.get('https://site.com/page2'); // same IP
40
+ ```
41
+
42
+ ## Geo-Targeting
43
+
44
+ ```javascript
45
+ const ip = new IPLoop('key', { country: 'JP' }); // All requests through Japan
46
+ // Or per-request:
47
+ const res = await ip.get('https://example.com', { country: 'GB' });
48
+ ```
49
+
50
+ ## TypeScript
51
+
52
+ Full TypeScript support included:
53
+
54
+ ```typescript
55
+ import IPLoop from 'iploop';
56
+ const ip = new IPLoop('your-api-key', { country: 'US' });
57
+ ```
58
+
59
+ ## API
60
+
61
+ - `ip.get(url, options?)` — GET request
62
+ - `ip.post(url, options?)` — POST request
63
+ - `ip.put(url, options?)` — PUT request
64
+ - `ip.delete(url, options?)` — DELETE request
65
+ - `ip.fetch(url, options?)` — Custom request
66
+ - `ip.session(options?)` — Create sticky session
67
+ - `ip.countries()` — List available countries
68
+
69
+ ## Links
70
+
71
+ - Website: [iploop.io](https://iploop.io)
72
+ - Twitter: [@iploop_io](https://x.com/iploop_io)
73
+
74
+ ## License
75
+
76
+ MIT
package/index.d.ts ADDED
@@ -0,0 +1,51 @@
1
+ declare class IPLoop {
2
+ constructor(apiKey: string, options?: {
3
+ gateway?: string;
4
+ port?: number;
5
+ country?: string;
6
+ city?: string;
7
+ timeout?: number;
8
+ });
9
+
10
+ fetch(url: string, options?: RequestOptions): Promise<IPLoopResponse>;
11
+ get(url: string, options?: RequestOptions): Promise<IPLoopResponse>;
12
+ post(url: string, options?: RequestOptions): Promise<IPLoopResponse>;
13
+ put(url: string, options?: RequestOptions): Promise<IPLoopResponse>;
14
+ delete(url: string, options?: RequestOptions): Promise<IPLoopResponse>;
15
+ session(options?: SessionOptions): IPLoopSession;
16
+ countries(): Promise<string[]>;
17
+ }
18
+
19
+ interface RequestOptions {
20
+ method?: string;
21
+ headers?: Record<string, string>;
22
+ body?: string | object;
23
+ country?: string;
24
+ city?: string;
25
+ session?: string;
26
+ timeout?: number;
27
+ }
28
+
29
+ interface SessionOptions {
30
+ country?: string;
31
+ city?: string;
32
+ session?: string;
33
+ }
34
+
35
+ interface IPLoopResponse {
36
+ status: number;
37
+ statusCode: number;
38
+ headers: Record<string, string>;
39
+ body: string;
40
+ text(): Promise<string>;
41
+ json(): Promise<any>;
42
+ }
43
+
44
+ declare class IPLoopSession {
45
+ fetch(url: string, options?: RequestOptions): Promise<IPLoopResponse>;
46
+ get(url: string, options?: RequestOptions): Promise<IPLoopResponse>;
47
+ post(url: string, options?: RequestOptions): Promise<IPLoopResponse>;
48
+ }
49
+
50
+ export = IPLoop;
51
+ export { IPLoop, IPLoopSession, RequestOptions, SessionOptions, IPLoopResponse };
package/index.js ADDED
@@ -0,0 +1,152 @@
1
+ const http = require('http');
2
+ const https = require('https');
3
+ const { URL } = require('url');
4
+
5
+ class IPLoop {
6
+ constructor(apiKey, options = {}) {
7
+ this.apiKey = apiKey;
8
+ this.gateway = options.gateway || 'gateway.iploop.io';
9
+ this.port = options.port || 8880;
10
+ this.country = options.country || null;
11
+ this.city = options.city || null;
12
+ this.timeout = options.timeout || 30000;
13
+ }
14
+
15
+ _buildAuth(options = {}) {
16
+ const parts = [this.apiKey];
17
+ const country = options.country || this.country;
18
+ const city = options.city || this.city;
19
+ const session = options.session || null;
20
+
21
+ if (country) parts.push(`country-${country}`);
22
+ if (city) parts.push(`city-${city}`);
23
+ if (session) parts.push(`session-${session}`);
24
+
25
+ return `user:${parts.join('-')}`;
26
+ }
27
+
28
+ fetch(url, options = {}) {
29
+ return new Promise((resolve, reject) => {
30
+ const target = new URL(url);
31
+ const auth = this._buildAuth(options);
32
+
33
+ const proxyOptions = {
34
+ hostname: this.gateway,
35
+ port: this.port,
36
+ path: url,
37
+ method: options.method || 'GET',
38
+ headers: {
39
+ ...this._defaultHeaders(target, options),
40
+ ...(options.headers || {}),
41
+ 'Proxy-Authorization': 'Basic ' + Buffer.from(auth).toString('base64'),
42
+ 'Host': target.hostname,
43
+ },
44
+ timeout: options.timeout || this.timeout,
45
+ };
46
+
47
+ const req = http.request(proxyOptions, (res) => {
48
+ let data = '';
49
+ res.on('data', chunk => data += chunk);
50
+ res.on('end', () => {
51
+ resolve({
52
+ status: res.statusCode,
53
+ statusCode: res.statusCode,
54
+ headers: res.headers,
55
+ text: () => Promise.resolve(data),
56
+ json: () => Promise.resolve(JSON.parse(data)),
57
+ body: data,
58
+ });
59
+ });
60
+ });
61
+
62
+ req.on('error', reject);
63
+ req.on('timeout', () => {
64
+ req.destroy();
65
+ reject(new Error('Request timeout'));
66
+ });
67
+
68
+ if (options.body) {
69
+ req.write(typeof options.body === 'string' ? options.body : JSON.stringify(options.body));
70
+ }
71
+ req.end();
72
+ });
73
+ }
74
+
75
+ get(url, options = {}) {
76
+ return this.fetch(url, { ...options, method: 'GET' });
77
+ }
78
+
79
+ post(url, options = {}) {
80
+ return this.fetch(url, { ...options, method: 'POST' });
81
+ }
82
+
83
+ put(url, options = {}) {
84
+ return this.fetch(url, { ...options, method: 'PUT' });
85
+ }
86
+
87
+ delete(url, options = {}) {
88
+ return this.fetch(url, { ...options, method: 'DELETE' });
89
+ }
90
+
91
+ session(options = {}) {
92
+ const sessionId = options.session || `sess-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
93
+ return new IPLoopSession(this, { ...options, session: sessionId });
94
+ }
95
+
96
+ _defaultHeaders(target, options = {}) {
97
+ const country = options.country || this.country || 'US';
98
+ const langs = {
99
+ US: 'en-US,en;q=0.9',
100
+ GB: 'en-GB,en;q=0.9',
101
+ DE: 'de-DE,de;q=0.9,en;q=0.8',
102
+ FR: 'fr-FR,fr;q=0.9,en;q=0.8',
103
+ JP: 'ja-JP,ja;q=0.9,en;q=0.8',
104
+ BR: 'pt-BR,pt;q=0.9,en;q=0.8',
105
+ IL: 'he-IL,he;q=0.9,en;q=0.8',
106
+ };
107
+
108
+ return {
109
+ 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36',
110
+ 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
111
+ 'Accept-Language': langs[country] || langs.US,
112
+ 'Accept-Encoding': 'gzip, deflate, br',
113
+ 'Cache-Control': 'no-cache',
114
+ 'Sec-Fetch-Dest': 'document',
115
+ 'Sec-Fetch-Mode': 'navigate',
116
+ 'Sec-Fetch-Site': 'none',
117
+ 'Sec-Ch-Ua': '"Chromium";v="122", "Not(A:Brand";v="24"',
118
+ 'Sec-Ch-Ua-Mobile': '?0',
119
+ 'Sec-Ch-Ua-Platform': '"Windows"',
120
+ 'Upgrade-Insecure-Requests': '1',
121
+ };
122
+ }
123
+
124
+ async countries() {
125
+ return ['US', 'GB', 'DE', 'FR', 'JP', 'BR', 'IN', 'AU', 'CA', 'IL',
126
+ 'KR', 'SG', 'NL', 'SE', 'CH', 'ES', 'IT', 'PL', 'TR', 'ZA',
127
+ 'NG', 'PH', 'MX', 'AR', 'CL', 'CO', 'EG', 'KE', 'TH', 'VN'];
128
+ }
129
+ }
130
+
131
+ class IPLoopSession {
132
+ constructor(client, options) {
133
+ this.client = client;
134
+ this.options = options;
135
+ }
136
+
137
+ fetch(url, options = {}) {
138
+ return this.client.fetch(url, { ...this.options, ...options });
139
+ }
140
+
141
+ get(url, options = {}) {
142
+ return this.fetch(url, { ...options, method: 'GET' });
143
+ }
144
+
145
+ post(url, options = {}) {
146
+ return this.fetch(url, { ...options, method: 'POST' });
147
+ }
148
+ }
149
+
150
+ module.exports = IPLoop;
151
+ module.exports.IPLoop = IPLoop;
152
+ module.exports.default = IPLoop;
package/package.json ADDED
@@ -0,0 +1,21 @@
1
+ {
2
+ "name": "iploop",
3
+ "version": "1.0.0",
4
+ "description": "IPLoop Residential Proxy SDK — route requests through millions of real devices",
5
+ "main": "index.js",
6
+ "types": "index.d.ts",
7
+ "keywords": ["proxy", "residential-proxy", "web-scraping", "rotating-proxy", "socks5", "http-proxy", "iploop", "sdk"],
8
+ "author": "IPLoop <partners@iploop.io>",
9
+ "license": "MIT",
10
+ "homepage": "https://iploop.io",
11
+ "repository": {
12
+ "type": "git",
13
+ "url": "https://github.com/iploop/iploop-node"
14
+ },
15
+ "engines": {
16
+ "node": ">=14"
17
+ },
18
+ "dependencies": {
19
+ "node-fetch": "^2.7.0"
20
+ }
21
+ }