# PAC file is served as UTF-16

Source: https://findproxyforurl.net/rules/pac-utf16-encoded/ · last updated 2026-10-13

Rule PAC-D013 (`pac-utf16-encoded`), severity high, category: Delivery (HTTP headers).

The file the server sends is stored as UTF-16 (it starts with the bytes FF FE or FE FF). Windows and Firefox cannot read it, so they run without a PAC file; only Chromium-based browsers cope.

## Why it matters

A PAC file is text, and the text has to be stored in an encoding the client reads. UTF-8 and
plain ASCII work everywhere. UTF-16 stores each character in two bytes and starts with a two-byte
marker, the byte order mark (FF FE or FE FF). Windows tools write UTF-16 without asking: Notepad's
"Unicode" setting, and in Windows PowerShell 5 the `>` redirection and `Out-File`. A PAC file
generated by a script on Windows is therefore often UTF-16.

In the lab, Windows (WinHTTP) could not load a UTF-16 PAC file (error 12166), while UTF-8 with
or without the UTF-8 byte order mark, and even Latin-1, loaded. Firefox reads the file as UTF-8
or Latin-1 only, so a UTF-16 file does not compile there. Chromium recognises the UTF-16 marker
and converts the file, which is why the problem can stay hidden when only Chrome is tested.
PAC-E013 reports the same problem for a file that you open in the checker; this rule reports it
for the bytes the server sends.


## How to fix

Save the file as UTF-8 or ASCII (PowerShell Set-Content -Encoding ascii, or Out-File -Encoding utf8) and check the first bytes; FF FE or FE FF means UTF-16.

## Bad

```js
first bytes: ff fe 66 00   (UTF-16LE: "f" followed by a zero byte)
```

## Good

```js
first bytes: 66 75 6e 63   ("func", UTF-8 or ASCII)
```

## Engine behaviour

- chromium: Without a charset in the Content-Type header, a UTF-16 or UTF-8 byte order mark selects the encoding; the file is converted and loads. (source: code, verified 2026-10-13)
- firefox: The file is compiled as UTF-8 when it is valid UTF-8, otherwise as Latin-1; UTF-16 is not recognised, so the zero bytes break the script. (source: code, verified 2026-10-13)
- winhttp: A UTF-16 file with byte order mark failed to load (error 12166). UTF-8 with or without byte order mark loaded; a Latin-1 file loaded with its non-ASCII characters garbled. (source: lab, verified 2026-10-11)
