[http] How can I use an http proxy with node.js http.Client?

I want to make an outgoing HTTP call from node.js, using the standard http.Client. But I cannot reach the remote server directly from my network and need to go through a proxy.

How do I tell node.js to use the proxy?

This question is related to http proxy node.js

The answer is


The 'request' http package seems to have this feature:

https://github.com/mikeal/request

For example, the 'r' request object below uses localproxy to access its requests:

var r = request.defaults({'proxy':'http://localproxy.com'})

http.createServer(function (req, resp) {
  if (req.url === '/doodle.png') {
    r.get('http://google.com/doodle.png').pipe(resp)
  }
})

Unfortunately there are no "global" defaults so that users of libs that use this cannot amend the proxy unless the lib pass through http options...

HTH, Chris


I bought private proxy server, after purchase I got:

255.255.255.255 // IP address of proxy server
99999 // port of proxy server
username // authentication username of proxy server
password // authentication password of proxy server

And I wanted to use it. First answer and second answer worked only for http(proxy) -> http(destination), however I wanted http(proxy) -> https(destination).

And for https destination it would be better to use HTTP tunnel directly. I found solution here. Final code:

const http = require('http')
const https = require('https')
const username = 'username'
const password = 'password'
const auth = 'Basic ' + Buffer.from(username + ':' + password).toString('base64')

http.request({
  host: '255.255.255.255', // IP address of proxy server
  port: 99999, // port of proxy server
  method: 'CONNECT',
  path: 'kinopoisk.ru:443', // some destination, add 443 port for https!
  headers: {
    'Proxy-Authorization': auth
  },
}).on('connect', (res, socket) => {
  if (res.statusCode === 200) { // connected to proxy server
    https.get({
      host: 'www.kinopoisk.ru',
      socket: socket,    // using a tunnel
      agent: false,      // cannot use a default agent
      path: '/your/url'  // specify path to get from server
    }, (res) => {
      let chunks = []
      res.on('data', chunk => chunks.push(chunk))
      res.on('end', () => {
        console.log('DONE', Buffer.concat(chunks).toString('utf8'))
      })
    })
  }
}).on('error', (err) => {
  console.error('error', err)
}).end()

In case you need to the use basic authorisation for your proxy provider, just use the following:

var http = require("http");

var options = {
    host:       FarmerAdapter.PROXY_HOST,
    port:       FarmerAdapter.PROXY_PORT,
    path:       requestedUrl,
    headers:    {
        'Proxy-Authorization':  'Basic ' + new Buffer(FarmerAdapter.PROXY_USER + ':' + FarmerAdapter.PROXY_PASS).toString('base64')
    }
};

var request = http.request(options, function(response) {
    var chunks = [];
    response.on('data', function(chunk) {
        chunks.push(chunk);
    });
    response.on('end', function() {
        console.log('Response', Buffer.concat(chunks).toString());
    });
});

request.on('error', function(error) {
    console.log(error.message);
});

request.end();

use 'https-proxy-agent' like this

var HttpsProxyAgent = require('https-proxy-agent');
var proxy = process.env.https_proxy || 'other proxy address';
var agent = new HttpsProxyAgent(proxy);

options = {
    //...
    agent : agent
}

https.get(options, (res)=>{...});

You can use request, I just found it's unbelievably easy to use proxy on node.js, just with one external "proxy" parameter, even more it supports HTTPS through a http proxy.

var request = require('request');

request({
  'url':'https://anysite.you.want/sub/sub',
  'method': "GET",
  'proxy':'http://yourproxy:8087'
},function (error, response, body) {
  if (!error && response.statusCode == 200) {
    console.log(body);
  }
})

Thought I would add this module I found: https://www.npmjs.org/package/global-tunnel, which worked great for me (Worked immediately with all my code and third party modules with only the code below).

require('global-tunnel').initialize({
  host: '10.0.0.10',
  port: 8080
});

Do this once, and all http (and https) in your application goes through the proxy.

Alternately, calling

require('global-tunnel').initialize();

Will use the http_proxy environment variable


Imskull's answer almost worked for me, but I had to make some changes. The only real change is adding username, password, and setting rejectUnauthorized to false. I couldn't comment so I put this in an answer.

If you run the code it'll get you the titles of the current stories on Hacker News, per this tutorial: http://smalljs.org/package-managers/npm/

var cheerio = require('cheerio');
var request = require('request');

request({
    'url': 'https://news.ycombinator.com/',
    'proxy': 'http://Username:Password@YourProxy:Port/',
    'rejectUnauthorized': false
}, function(error, response, body) {
    if (!error && response.statusCode == 200) {
        if (response.body) {
            var $ = cheerio.load(response.body);
            $('td.title a').each(function() {
                console.log($(this).text());
            });
       }
    } else {
        console.log('Error or status not equal 200.');
    }
});

One thing that took me a while to figure out, use 'http' to access the proxy, even if you're trying to proxy through to a https server. This works for me using Charles (osx protocol analyser):

var http = require('http');

http.get ({
    host: '127.0.0.1',
    port: 8888,
    path: 'https://www.google.com/accounts/OAuthGetRequestToken'
}, function (response) {
    console.log (response);
});

Node should support using the http_proxy environmental variable - so it is cross platform and works on system settings rather than requiring a per-application configuration.

Using the provided solutions, I would recommend the following:

Coffeescript

get_url = (url, response) ->
  if process.env.http_proxy?
    match = process.env.http_proxy.match /^(http:\/\/)?([^:\/]+)(:([0-9]+))?/i
    if match
      http.get { host: match[2], port: (if match[4]? then match[4] else 80), path: url }, response
      return
  http.get url, response

Javascript

get_url = function(url, response) {
  var match;
  if (process.env.http_proxy != null) {
    match = process.env.http_proxy.match(/^(http:\/\/)?([^:\/]+)(:([0-9]+))?/i);
    if (match) {
      http.get({
        host: match[2],
        port: (match[4] != null ? match[4] : 80),
        path: url
      }, response);
      return;
    }
  }
  return http.get(url, response);
};

Usage To use the method, effectively just replace http.get, for instance the following writes the index page of google to a file called test.htm:

file = fs.createWriteStream path.resolve(__dirname, "test.htm")
get_url "http://www.google.com.au/", (response) ->
  response.pipe file
  response.on "end", ->
    console.log "complete"

As @Renat here already mentioned, proxied HTTP traffic comes in pretty normal HTTP requests. Make the request against the proxy, passing the full URL of the destination as the path.

var http = require ('http');

http.get ({
    host: 'my.proxy.com',
    port: 8080,
    path: 'http://nodejs.org/'
}, function (response) {
    console.log (response);
});

May not be the exact one-liner you were hoping for but you could have a look at http://github.com/nodejitsu/node-http-proxy as that may shed some light on how you can use your app with http.Client.


http://groups.google.com/group/nodejs/browse_thread/thread/d5aadbcaa00c3f7/12ebf01d7ec415c3?lnk=gst&q=proxy#12ebf01d7ec415c3

Based on the answers from this thread it would seem like you could use proxychains to run node.js through the proxy server:
$ proxychains /path/to/node application.js

Personally I wasnt able to install any of the proxychains versions on Cygwin/Windows environment so couldn't test it.

Furthermore, they also talked about using connect-proxy but I could not find any documentation on how to do this.

In short, I'm still stuck, but maybe someone can use this info to find a suitable work-around.


I think there a better alternative to the answers as of 2019. We can use the global-tunnel-ng package to initialize proxy and not pollute the http or https based code everywhere. So first install global-tunnel-ng package:

npm install global-tunnel-ng

Then change your implementations to initialize proxy if needed as:

const globalTunnel = require('global-tunnel-ng');

globalTunnel.initialize({
  host: 'proxy.host.name.or.ip',
  port: 8080
});


If you have the Basic http authentication scheme you have to make a base64 string of myuser:mypassword, and then add "Basic" in the beginning. That's the value of Proxy-Authorization header, here an example:

var Http = require('http');

var req = Http.request({
    host: 'myproxy.com.zx',
    port: 8080,
    headers:{"Proxy-Authorization": "Basic bXl1c2VyOm15cGFzc3dvcmQ="},
    method: 'GET',
    path: 'http://www.google.com/'
    }, function (res) {
        res.on('data', function (data) {
        console.log(data.toString());
    });
});

req.end();

In nodejs you could use Buffer to encode

var encodedData = Buffer.from('myuser:mypassword').toString('base64');

console.log(encodedData);

Just as example, in browsers you could encode in base64 using btoa(), useful in ajax requests in a browser without proxy settings performing a request using proxy.

_x000D_
_x000D_
var encodedData = btoa('myuser:mypassword')_x000D_
_x000D_
console.log(encodedData);
_x000D_
_x000D_
_x000D_

How to find wich scheme accepts the proxy server?

If we don't have a custom DNS configured (that would throw something like ERR_NAME_NOT_RESOLVED), when we perform a request, the response (code 407) should inform in the response headers which http authentication scheme the proxy is using.


For using a proxy with https I tried the advice on this website (using dependency https-proxy-agent) and it worked for me:

http://codingmiles.com/node-js-making-https-request-via-proxy/


Basically you don't need an explicit proxy support. Proxy protocol is pretty simple and based on the normal HTTP protocol. You just need to use your proxy host and port when connecting with HTTPClient. Example (from node.js docs):

var http = require('http');
var google = http.createClient(3128, 'your.proxy.host');
var request = google.request('GET', '/',
  {'host': 'www.google.com'});
request.end();
...

So basically you connect to your proxy but do a request to "http://www.google.com".


Examples related to http

Access blocked by CORS policy: Response to preflight request doesn't pass access control check Axios Delete request with body and headers? Read response headers from API response - Angular 5 + TypeScript Android 8: Cleartext HTTP traffic not permitted Angular 4 HttpClient Query Parameters Load json from local file with http.get() in angular 2 Angular 2: How to access an HTTP response body? What is HTTP "Host" header? Golang read request body Angular 2 - Checking for server errors from subscribe

Examples related to proxy

Axios having CORS issue Running conda with proxy WebSockets and Apache proxy : how to configure mod_proxy_wstunnel? "Proxy server connection failed" in google chrome Set proxy through windows command line including login parameters Could not resolve all dependencies for configuration ':classpath' Problems using Maven and SSL behind proxy Using npm behind corporate proxy .pac git returns http error 407 from proxy after CONNECT Forwarding port 80 to 8080 using NGINX

Examples related to node.js

Hide Signs that Meteor.js was Used Querying date field in MongoDB with Mongoose SyntaxError: Cannot use import statement outside a module Server Discovery And Monitoring engine is deprecated How to fix ReferenceError: primordials is not defined in node UnhandledPromiseRejectionWarning: This error originated either by throwing inside of an async function without a catch block dyld: Library not loaded: /usr/local/opt/icu4c/lib/libicui18n.62.dylib error running php after installing node with brew on Mac internal/modules/cjs/loader.js:582 throw err DeprecationWarning: Buffer() is deprecated due to security and usability issues when I move my script to another server Please run `npm cache clean`