npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

javascript-proxy-headers

v0.2.1

Published

Extensions for JavaScript HTTP libraries to support sending and receiving custom proxy headers during HTTPS CONNECT tunneling

Downloads

175

Readme

npm version

JavaScript Proxy Headers

Extensions for JavaScript HTTP libraries to support sending and receiving custom proxy headers during HTTPS CONNECT tunneling.

The Problem

When making HTTPS requests through a proxy, the connection is established via a CONNECT tunnel. During this process:

  1. Sending headers to the proxy - Most JavaScript HTTP libraries don't provide a way to send custom headers (like X-ProxyMesh-Country) to the proxy server during the CONNECT handshake.

  2. Receiving headers from the proxy - The proxy's response headers from the CONNECT request are typically discarded, making it impossible to read custom headers (like X-ProxyMesh-IP) that the proxy sends back.

This library solves both problems for popular JavaScript HTTP libraries.

Supported Libraries

| Library | Subpath export | Notes | |---------|----------------|--------| | axios | javascript-proxy-headers/axios | Widely used client | | node-fetch | javascript-proxy-headers/node-fetch | Fetch API on Node | | got | javascript-proxy-headers/got | Ergonomic API | | undici | javascript-proxy-headers/undici | Node’s fast HTTP stack | | superagent | javascript-proxy-headers/superagent | Chaining API | | ky | javascript-proxy-headers/ky | Tiny fetch wrapper | | wretch | javascript-proxy-headers/wretch | Fetch wrapper (sets wretch’s global fetch polyfill) | | make-fetch-happen | javascript-proxy-headers/make-fetch-happen | npm-style fetch (cache, retries, proxy) | | needle | javascript-proxy-headers/needle | Lean HTTP client | | typed-rest-client | javascript-proxy-headers/typed-rest-client | Azure / DevOps–style REST client |

urllib is not integrated yet: it expects an undici Dispatcher, not a Node Agent. See notes/urllib-integration-deferred.md in this repo for a possible approach.

Installation

npm install javascript-proxy-headers

Then install the HTTP client(s) you use (for example axios, got, ky, wretch, make-fetch-happen, needle, or typed-rest-client). Each is an optional peer dependency.

Note: This package has no runtime dependencies by default—install only the adapters you need.

Quick Start

axios

import { createProxyAxios } from 'javascript-proxy-headers/axios';

const client = createProxyAxios({
    proxy: 'http://user:[email protected]:8080',
    proxyHeaders: { 'X-ProxyMesh-Country': 'US' }
});

const response = await client.get('https://httpbin.org/ip');

// Proxy headers are merged into response.headers
console.log(response.headers['x-proxymesh-ip']);

node-fetch

import { proxyFetch } from 'javascript-proxy-headers/node-fetch';

const response = await proxyFetch('https://httpbin.org/ip', {
    proxy: 'http://user:[email protected]:8080',
    proxyHeaders: { 'X-ProxyMesh-Country': 'US' }
});

// Proxy headers available on response
console.log(response.proxyHeaders.get('x-proxymesh-ip'));

got

import { createProxyGot } from 'javascript-proxy-headers/got';

const client = createProxyGot({
    proxy: 'http://user:[email protected]:8080',
    proxyHeaders: { 'X-ProxyMesh-Country': 'US' }
});

const response = await client('https://httpbin.org/ip');
console.log(response.headers['x-proxymesh-ip']);

undici

import { request } from 'javascript-proxy-headers/undici';

const { statusCode, headers, body, proxyHeaders } = await request(
    'https://httpbin.org/ip',
    {
        proxy: 'http://user:[email protected]:8080',
        proxyHeaders: { 'X-ProxyMesh-Country': 'US' }
    }
);

console.log(proxyHeaders.get('x-proxymesh-ip'));

ky

Uses a custom fetch built from node-fetch + ProxyHeadersAgent (ky.create({ fetch })).

import { createProxyKy } from 'javascript-proxy-headers/ky';

const api = await createProxyKy({
    proxy: 'http://user:[email protected]:8080',
    proxyHeaders: { 'X-ProxyMesh-Country': 'US' }
});

const response = await api('https://httpbin.org/ip');
console.log(response.proxyHeaders.get('x-proxymesh-ip'));

wretch

Registers the same custom fetch as wretch’s fetch polyfill. Use the normal wretch chain (for example .get().res()).

import { createProxyWretch } from 'javascript-proxy-headers/wretch';

const wretch = await createProxyWretch({
    proxy: 'http://user:[email protected]:8080',
    proxyHeaders: { 'X-ProxyMesh-Country': 'US' }
});

const response = await wretch('https://httpbin.org/ip').get().res();
console.log(response.proxyHeaders.get('x-proxymesh-ip'));

make-fetch-happen

Passes a ProxyHeadersAgent as agent; @npmcli/agent uses it as-is when set.

import { createProxyMakeFetchHappen } from 'javascript-proxy-headers/make-fetch-happen';

const fetch = createProxyMakeFetchHappen({
    proxy: 'http://user:[email protected]:8080',
    proxyHeaders: { 'X-ProxyMesh-Country': 'US' }
});

const response = await fetch('https://httpbin.org/ip');
console.log(response.proxyHeaders.get('x-proxymesh-ip'));

needle

import { proxyNeedleGet } from 'javascript-proxy-headers/needle';

const res = await proxyNeedleGet('https://httpbin.org/ip', {
    proxy: 'http://user:[email protected]:8080',
    proxyHeaders: { 'X-ProxyMesh-Country': 'US' }
});

// CONNECT response headers merged onto res.headers where missing
console.log(res.headers['x-proxymesh-ip']);

typed-rest-client

Uses a subclass of HttpClient that routes HTTPS through ProxyHeadersAgent (no tunnel agent).

import { createProxyRestClient } from 'javascript-proxy-headers/typed-rest-client';

const client = createProxyRestClient({
    userAgent: 'my-app',
    proxy: 'http://user:[email protected]:8080',
    proxyHeaders: { 'X-ProxyMesh-Country': 'US' }
});

await client.get('https://httpbin.org/ip');
console.log(client.proxyAgent.lastProxyHeaders?.get('x-proxymesh-ip'));

Core Agent (Advanced)

For direct control, use the core ProxyHeadersAgent:

import { ProxyHeadersAgent } from 'javascript-proxy-headers';
import https from 'https';

const agent = new ProxyHeadersAgent('http://proxy.example.com:8080', {
    proxyHeaders: { 'X-ProxyMesh-Country': 'US' },
    onProxyConnect: (headers) => {
        console.log('Proxy IP:', headers.get('x-proxymesh-ip'));
    }
});

https.get('https://httpbin.org/ip', { agent }, (res) => {
    // Handle response
});

Testing

Integration tests need a real proxy (set PROXY_URL or HTTPS_PROXY):

export PROXY_URL='http://user:[email protected]:8080'

npm test                              # all adapters (see package.json "test")
node run_tests.js -v                  # same harness from repo root
npm run test:ts                       # same checks via tsx + TypeScript harness
npm run test:types                    # `tsc --noEmit` only (no network)

# Limit modules
node test/test_proxy_headers.js -v axios ky

Verbose (-v) prints captured header values. See test/test_proxy_headers.js --help.

Requirements

  • Node.js >= 18.0.0
  • One or more supported HTTP libraries

Related Projects

About

Created by ProxyMesh to help our customers use custom headers to control proxy behavior. Works with any proxy that supports custom headers.

License

MIT License