---
title: "Proxies for git, npm and pip"
url: https://proxy.wiki/guides/proxies-for-git-npm-pip/
type: Guide
author: "proxy.wiki editorial"
published: 2026-09-01
updated: 2026-09-01
site: proxy.wiki
topics: ["Web scraping"]
license: CC BY 4.0 — quote freely with attribution to https://proxy.wiki/
---

# Proxies for git, npm and pip

> git config https.proxy is silently ignored, npm's equivalent works, and pip blames the package. Every setting tested against a closed port.

## Key takeaways

- git config https.proxy is silently ignored. The key is http.proxy, and it applies to https:// remotes too.
- npm is the opposite: both npm config set proxy and https-proxy work. Carrying git's model across breaks here.
- All three ignore http_proxy when the endpoint is HTTPS. Setting only that variable configures nothing.
- pip's proxy failure reads "Could not find a version that satisfies the requirement" and never mentions the proxy.
- Test by pointing the setting at a closed port. If the command still succeeds, the tool ignored your configuration.
- npm answers from its cache, so point --cache at a fresh directory or you will measure the cache, not the proxy.

Three developer tools, three different proxy settings, and one of them is a trap: the option that looks correct in git does nothing at all, and it fails silently. This guide gives the working configuration for each, the errors they produce when it goes wrong, and how to prove the proxy is actually being used.

Everything below was produced by pointing each setting at a port that refuses connections. If the command fails, the setting was honoured. If it succeeds, the tool ignored the setting and went direct. Each tool has a passing no-proxy control, so a failure means the proxy rather than a broken test.

## The short answer

| Setting | git 2.50.1 | pip 25.0 | npm 11.6.3 |
| --- | --- | --- | --- |
| https_proxy / HTTPS_PROXY | Honoured | Honoured | Honoured |
| http_proxy / HTTP_PROXY | Ignored | Ignored | Ignored |
| ALL_PROXY / all_proxy | Honoured | Not tested | Not tested |
| The tool’s own option | http.proxy | --proxy | --proxy |
| An https variant of that option | Ignored | None exists | --https-proxy works |
| no_proxy bypass | Honoured | Honoured | --noproxy |

Two rows are worth pausing on. Every one of the three ignores `http_proxy` when the endpoint is HTTPS, which is correct behaviour and still surprises people who set only that one. And the fifth row is where git and npm disagree completely.

## git: http.proxy is the key, even for HTTPS

This is the mistake that costs the most time, because the wrong configuration reports success.

```
# Works. Applies to https:// remotes as well.
git config --global http.proxy http://gateway.example:8000

# Does nothing at all. No error, no warning, traffic goes direct.
git config --global https.proxy http://gateway.example:8000
```

Tested by pointing each at a closed port. With `http.proxy` the clone failed, which proves git tried to use it. With `https.proxy` the clone _succeeded_ — git ignored the setting entirely and connected straight to the remote.

The reason is that git has no such key. Its proxy configuration is `http.proxy` regardless of the URL scheme, plus the URL-scoped form `http.<url>.proxy` for per-host rules. Writing `https.proxy` creates a config entry that nothing ever reads, and `git config --list` will happily show it back to you.

Per-host configuration uses the same key with a URL in the middle:

```
# Only this host goes through the proxy
git config --global http.https://github.com/.proxy http://gateway.example:8000

# Everything except this host
git config --global http.proxy http://gateway.example:8000
git config --global http.https://internal.example/.proxy ""
```

The empty string in the second form is the documented way to say “no proxy for this one”, and it is more reliable than `no_proxy` because it lives with the rest of your git configuration rather than in the shell that happened to start the command.

## npm: the opposite convention

npm accepts both spellings, and both work:

```
npm config set proxy       http://gateway.example:8000
npm config set https-proxy http://gateway.example:8000
```

Both were confirmed against a closed port, and both failed as expected. So the option that is a no-op in git is functional in npm. If you carry a mental model from one tool to the other, this is where it breaks.

npm spells its exemption list differently too. It is `noproxy`, one word, not `no_proxy`:

```
npm config set noproxy registry.internal.example,localhost
```

One caution when testing npm: it answers from its cache. A command that succeeds through a deliberately broken proxy may simply have avoided the network. Point `--cache` at a fresh temporary directory when you are checking proxy behaviour, or you will measure the cache instead.

## pip

pip is the most conventional of the three. It reads the environment, and it has one flag:

```
# Per command
pip install --proxy http://gateway.example:8000 requests

# Persistent, in pip.conf
[global]
proxy = http://gateway.example:8000
```

Both the environment variables and `--proxy` were confirmed working. `no_proxy` is honoured, and it needs both hosts when you exempt PyPI, because packages are downloaded from a different domain than the index:

```
export no_proxy="pypi.org,files.pythonhosted.org"
```

Exempting only the first leaves every actual download still going through the proxy, which is the kind of half-configuration that produces an intermittent failure rather than an obvious one.

## Reading the errors

The three tools differ enormously in how clearly they report a proxy failure. Each line below was produced deliberately, with the proxy pointed at a closed port or an unresolvable host.

| Tool | What it prints | Does it name the proxy? |
| --- | --- | --- |
| git, port closed | fatal: unable to access ... Failed to connect to 127.0.0.1 port 9 | Shows the address |
| git, host unresolvable | fatal: ... Could not resolve proxy: no-such-proxy.invalid | Yes, explicitly |
| npm | npm error code ECONNREFUSED / syscall connect | Implies it |
| pip | ERROR: Could not find a version that satisfies the requirement six | No. It blames the package. |

The pip row is the one to remember. A broken proxy produces a message that reads exactly like a package that does not exist, followed by `No matching distribution found`. Nothing in the output mentions a proxy, a connection or a network. People spend real time checking spelling and package availability before suspecting the thing that is actually wrong.

The rule that saves the time: **if a package manager says a package cannot be found, and you are behind a proxy, test the proxy before you test the package name.**

## Proving the proxy is applied

Do not infer this from the absence of errors. A tool that ignores your setting succeeds quietly, which looks identical to a tool that used the proxy correctly.

The reliable test is to point the setting at a port where nothing is listening. A configuration that is being honoured must fail:

```
# If these succeed, the setting is being ignored
https_proxy=http://127.0.0.1:9 git ls-remote https://github.com/octocat/Hello-World.git
https_proxy=http://127.0.0.1:9 pip download six --no-deps -d /tmp/x
https_proxy=http://127.0.0.1:9 npm view express version
```

Run the same three commands with the variable unset first. If they fail then too, you have a network problem rather than a proxy result, and every conclusion you draw from the test would be wrong.

For a stronger check, run a proxy that logs what it is asked for and confirm the connection appears. A tool that never contacts the proxy leaves nothing in that log, whatever its exit code says.

## Where each setting is stored

Once you stop passing the proxy per command, it has to live in a file, and each tool keeps its own. Knowing which file also tells you where a stale setting will be hiding when the proxy changes.

| Tool | Per-user file | How to find it |
| --- | --- | --- |
| git | ~/.gitconfig, or $XDG_CONFIG_HOME/git/config | git config --global --list --show-origin |
| npm | ~/.npmrc | npm config get userconfig |
| pip | ~/.pip/pip.conf or ~/.config/pip/pip.conf | pip config debug |

Each also has a system-wide layer above the per-user one — `/etc/gitconfig`, an `npmrc` beside the npm installation, and a global `pip.conf`. On a machine somebody else set up, a proxy you cannot find in your own files is usually sitting in one of those.

The commands in the third column are worth running before you debug anything else. `--show-origin` and `pip config debug` both report which file a value came from, which turns “why is it still using the old proxy” into a one-line answer.

## Keep the password out of the file

A proxy URL with inline credentials leaks in more places than people expect. In these three tools specifically it ends up in `git config --list` output, in `~/.npmrc` as plain text, and in any CI log that echoes the environment.

```
# Avoid: the password is now in a file, in shell history, and in --list output
git config --global http.proxy http://user:pass@gateway.example:8000
```

Where the provider supports it, prefer an [address allow-list](/glossary/ip-whitelisting/) so no secret travels with the request at all. Where credentials are unavoidable, keep them in an environment variable supplied at run time rather than written into a config file, and make sure whatever prints your configuration for debugging redacts it.

## Where none of this reaches

All three tools read the environment of the process that runs them. That means the settings apply only where they were inherited, and three boundaries commonly break them.

- **A container does not inherit your shell.** Variables exported in your terminal are not passed to `docker run` unless you name them, and a build runs each step in its own container again. Pulling the image is a third case, made by the daemon rather than your shell.

- **A service manager does not inherit your login shell.** A unit started by systemd, or a job started by cron, gets the environment it is given. Exporting a variable in a shell profile and restarting the service changes nothing.

- **CI runners start clean.** The proxy that works on your laptop is absent in the pipeline unless the pipeline sets it, which is why “works locally, fails in CI” is the standard symptom.

For the general behaviour of these variables across runtimes, including the case rule that makes uppercase `HTTP_PROXY` unreliable, see [the environment-variable guide](/guides/proxy-environment-variables/). The [authentication](/glossary/proxy-authentication/) notes there apply here too: a proxy URL containing a password ends up in shell history, in `git config --list` output and in CI logs.

## How this was tested

Each setting was pointed at `http://127.0.0.1:9`, a port that refuses connections, so that a successful command proves the setting was skipped and a failed one proves it was attempted. Every tool was given a control run with no proxy set; where that control failed, the results were discarded rather than reported.

That control mattered. Two earlier versions of this test produced a clean-looking table in which every setting appeared to be honoured, and both were wrong: in one the test harness was failing before the tool ran, and in the other the shell was not splitting the command as intended. In both cases the failure looked exactly like a proxy being used. The tables above come from the run where all three controls passed.

Versions: git 2.50.1, pip 25.0, npm 11.6.3, on macOS, on 1 September 2026. Behaviour changes between releases, so run the closed-port check against your own versions rather than trusting a table.

Docker is deliberately absent. We could not run a daemon on the test machine, and we do not publish configuration we have not executed.

## Frequently asked questions

### Why does git config https.proxy not work?

Because git has no such key. Its proxy setting is http.proxy regardless of the URL scheme, plus the URL-scoped form http.<url>.proxy for per-host rules. Writing https.proxy creates an entry nothing reads, and git config --list will still show it back to you, which is why the mistake survives so long.

### Which environment variable should I set for git, npm and pip?

https_proxy, in lowercase, for all three. Every one of them ignores http_proxy when the endpoint is HTTPS, and package registries and git remotes are almost always HTTPS today. Setting both cases costs nothing and removes the question.

### pip says it cannot find the package. Is that really a proxy problem?

It can be. A broken proxy makes pip print "Could not find a version that satisfies the requirement" followed by "No matching distribution found", with no mention of a proxy or a network. If you are behind a proxy, test the proxy before you check the package name.

### How do I exempt an internal host from the proxy?

For git, set an empty URL-scoped value: git config http.https://internal.example/.proxy "". That lives with your git configuration rather than in the shell. For pip, use no_proxy and remember to list files.pythonhosted.org as well as pypi.org, because downloads come from a different domain than the index. For npm, the setting is spelled noproxy, one word.

### Why did my npm proxy test pass when the proxy was broken?

npm answered from its cache without touching the network. Point --cache at a fresh temporary directory when you are testing proxy behaviour, otherwise you are measuring the cache rather than the connection.

### How can I be sure the proxy is actually being used?

Point it at a port where nothing is listening. A setting that is being honoured must make the command fail. Run the same command with the variable unset first; if that fails too, you have a network problem and the test proves nothing.

## Sources

1. [git config: the http.proxy and http.<url>.proxy settings](https://git-scm.com/docs/git-config)
2. [pip user guide: proxy configuration and config files](https://pip.pypa.io/en/stable/user_guide/)
3. [npm config: proxy, https-proxy and noproxy](https://docs.npmjs.com/cli/v11/using-npm/config)
