# FindProxyForURL(url, host)

Source: https://findproxyforurl.net/findproxyforurl/ · updated 2026-10-06

FindProxyForURL(url, host) is the one function every proxy.pac or wpad.dat file must define. The browser calls it for each request and follows the string it returns, either DIRECT or a list of proxies to try in order.

## Signature

```js
function FindProxyForURL(url, host) {
  // ...
  return "PROXY proxy.corp.example:8080";
}
```

- `url`: the URL of the request, for example `http://www.example.com/path?q=1`. What the script
  really sees depends on the engine (see below).
- `host`: the host name taken from that URL, without the port, for example `www.example.com`.

The names `url` and `host` are a convention. The engine passes the arguments by position
([PAC-B002](https://findproxyforurl.net/rules/nonstandard-parameter-names/)).

## Return values

| Return value | Meaning |
|---|---|
| `DIRECT` | connect without a proxy |
| `PROXY host:port` | use an HTTP proxy |
| `SOCKS host:port` | use a SOCKS proxy; the version differs between engines ([PAC-K005](https://findproxyforurl.net/rules/socks-version-keyword/)) |
| `HTTPS host:port` | TLS to the proxy itself; Chromium and Firefox only ([PAC-K006](https://findproxyforurl.net/rules/https-proxy-keyword-without-fallback/)) |

Separate several entries with semicolons. The browser tries them in order and moves to the next one
when a proxy cannot be reached: `"PROXY p1.corp.example:8080; PROXY p2.corp.example:8080"`. Ending the
list with `DIRECT` means a dead proxy silently becomes direct internet access. Make that a decision,
not a default. Always write a port ([PAC-X013](https://findproxyforurl.net/rules/proxy-without-port/)), and keep the port between
1 and 65535 ([PAC-E012](https://findproxyforurl.net/rules/invalid-proxy-port/)).

## A minimal correct example

```js
function FindProxyForURL(url, host) {
  host = host.toLowerCase();
  // internal names and domains go direct
  if (isPlainHostName(host) || dnsDomainIs(host, ".corp.example")) {
    return "DIRECT";
  }
  // default route: always the last statement
  return "PROXY proxy1.corp.example:8080; PROXY proxy2.corp.example:8080";
}
```

The helper functions it can call (`isPlainHostName`, `dnsDomainIs`, `shExpMatch`, `isInNet` and
others) are listed in the [PAC function reference](https://findproxyforurl.net/functions/).

## How engines differ

These rows come from reading each engine's source code at the commit given on its
[engine page](https://findproxyforurl.net/engines/). "expert" rows have not been confirmed in code or in a lab run yet.

| Behaviour | Chromium (Chrome, Edge) | Firefox | pacparser (pactester) | Source, date |
|---|---|---|---|---|
| `url` for `https://` requests | path and query removed (Chrome ≥ 52) | path and query removed for every scheme (default setting) | passed unchanged | code, 2026-10-04 |
| No return / non-string result | connects directly | connects directly | returns the string `undefined` | code, 2026-10-04 |
| Script throws an exception | connects directly | connects directly | error, no result | code, 2026-10-04 |
| Calls `FindProxyForURLEx` if defined | no | no | yes | code, 2026-10-04 |
| `host` lower-cased by the engine | yes | yes | no (code) | expert, unverified (Chromium, Firefox) |

Consequences:

- A PAC that tests the path or query of `url` behaves differently in Chrome, Firefox and
  `pactester`. Decide on `host` ([PAC-C001](https://findproxyforurl.net/rules/url-instead-of-host/)).
- A missing default `return` sends traffic around the proxy in every browser, without an error
  ([PAC-X001](https://findproxyforurl.net/rules/no-default-return/)).
- A file that only defines `FindProxyForURLEx` does nothing in browsers
  ([PAC-K004](https://findproxyforurl.net/rules/findproxyforurlex-only/)).
- Lower-case `host` yourself (`host = host.toLowerCase();`) so every engine compares the same string.

## Test it

Paste your file into the [online PAC file tester](https://findproxyforurl.net/check/). It runs `FindProxyForURL` for your URLs
in each engine profile, shows which line decided each result and rates the file against the
[rule catalogue](https://findproxyforurl.net/rules/).

## References

- [MDN: Proxy Auto-Configuration (PAC) file](https://developer.mozilla.org/en-US/docs/Web/HTTP/Proxy_servers_and_tunneling/Proxy_Auto-Configuration_PAC_file)
- Engine source references: [Chromium](https://findproxyforurl.net/engines/chromium/), [Firefox](https://findproxyforurl.net/engines/firefox/),
  [pacparser](https://findproxyforurl.net/engines/pacparser/)


## Frequently asked questions

### What does FindProxyForURL return?

A string. "DIRECT" means connect without a proxy, "PROXY host:port" means use that HTTP proxy, and "SOCKS host:port" means a SOCKS proxy. Several entries separated by semicolons are tried in order, for example "PROXY p1.example:8080; PROXY p2.example:8080".

### What happens if FindProxyForURL returns nothing or throws an error?

Chromium and Firefox treat it as a script failure and connect directly, so traffic silently bypasses the proxy. pacparser (pactester) returns the string "undefined" or reports an error. Always end the function with an unconditional return.

### Should I test url or host?

Test host for domain decisions. url contains the path and query string, which anyone can choose, and browsers cut parts of it off (Chrome removes the path and query of https URLs before calling the function).

### How do I test a FindProxyForURL function?

Paste the file into the online PAC file tester at findproxyforurl.net/check/. It runs the function for your URLs in Chromium, Firefox and pacparser engine profiles and shows where they disagree.

