# pdf_viewer

> Whether the browser says it shows PDF files itself, from navigator.pdfViewerEnabled.

Source: https://whiskerjs.com/signals/pdf-viewer/ (last updated 2026-10-26)

**pdf_viewer at a glance (from the library code, signalsVersion 9)**

| Field | Value |
| --- | --- |
| Component name | `pdf_viewer` |
| In the visitorId | yes |
| structuredId group | [browser (engine and build)](https://whiskerjs.com/docs/identifiers/#structuredid) |
| Hashing | plain value; a digest only when longer than 128 characters or not printable ASCII |
| Excluded under | no browser class |
| Inner timeout | 1000 ms |
| Added in | [signalsVersion 1](https://whiskerjs.com/whats-new/) |

> **In plain words:**
>
> Most desktop browsers can show PDF files themselves. They also tell web pages whether that built-in viewer is on. WhiskerJS records that yes or no. It is a small signal: it mainly separates normal browsers from headless, embedded or specially configured ones.

## What it reads

`navigator.pdfViewerEnabled`, a boolean.

## How the technique works

The property is read once. `true` and `false` are reported as the plain words `true` and `false`. Any other type (the property is missing) gives `unavailable`. If the property’s getter throws, the error is not swallowed, so the component reports `blocked` instead of pretending the property is missing.

## Why it helps

The answer is the same for nearly every normal desktop browser, so on its own it tells few devices apart. It earns its place in the `browser` group because it separates groups that are otherwise similar: browsers where a policy or the user turned the viewer off, embedded browser views, and many headless and automation setups.

On your server, a `false` value is not suspicious by itself. It becomes interesting together with other hints: for example `false` with an empty [`plugins`](https://whiskerjs.com/signals/plugins/) list, a [`software_renderer`](https://whiskerjs.com/docs/integrity/#software_renderer) flag and a desktop user agent describes many automated setups, while the same `false` on a managed office computer may just be a policy.

## Stability

Very stable. It changes only when the user or an administrator changes the PDF setting, or the browser changes its default.

## Browser support and what blocks it

- Current desktop [Chrome](https://whiskerjs.com/browsers/chrome-desktop/), [Edge](https://whiskerjs.com/browsers/edge/), [Firefox](https://whiskerjs.com/browsers/firefox/), [Safari](https://whiskerjs.com/browsers/safari-macos/) and [Brave](https://whiskerjs.com/browsers/brave/) expose the property; usually `true`.
- Mobile browsers may report either value, depending on whether the browser itself shows PDFs.
- Older browsers without the property report `unavailable` / `no_api`.

No browser class excludes it.

## Privacy

A yes-or-no setting shared by most users. It reveals nothing personal.

## How WhiskerJS handles noise and failures

| Status | ruleId | When |
| --- | --- | --- |
| `ok` |   | `true` or `false` |
| `unavailable` | `no_api` | the property is not a boolean (missing) |
| `blocked` | `threw`, `security_error` | the getter throws |
| `excluded` | `caller_excluded` | you excluded it |
| `timed_out` | `timeout`, `aborted` | budget or abort |

Never hashed.

## Example value

In the container test, headless Chromium and Firefox reported `false` and headless WebKit reported `true`. A normal desktop Chrome usually reports `true`.

## Questions and answers

### Why is pdf_viewer false in my headless test browser?

Headless and embedded browsers often have no built-in PDF viewer, and some users turn it off so that PDFs download instead. Both give false.

### Does WhiskerJS open a PDF to check?

No. It only reads the navigator.pdfViewerEnabled property.

## Related pages

- [plugins](https://whiskerjs.com/signals/plugins/): The plugin list, which in current browsers mostly mirrors the PDF viewer.
- [headless_markers flag](https://whiskerjs.com/docs/integrity/#headless_markers): Other traits of headless browsers.
- [browser_class](https://whiskerjs.com/signals/browser-class/): The browser family guess.
