# PDFDocument.save()

```ts
save(): Promise<Uint8Array>
```

Resolves to the document's bytes, a `Uint8Array`: every change made through the API and, with a viewer open, the values its form fields hold — not a signature drawn on screen (use [`viewer.createExporter()`](https://kernstra.com/docs/web-sdk/api/pdfviewer/createexporter) for that, when a viewer is on screen and you want everything the user sees). Values set with `doc.forms` while no viewer was open are in the document, and so in the save. Needs the `export` feature.

A document opened with a digital signature is saved as an **incremental update**: the bytes it was signed over, untouched, then **one** update with what changed — nothing the session passed through on the way is in the file, and a document saved unchanged comes back as the signed file itself. A change the signature's certification allows then reads in Acrobat as a change made after signing, not as a broken signature. Any other document is written afresh. Saving stamps the saved copy's modification date; the open document is left as it was, and a PDF/A file nobody changed is saved as it was opened. Encryption applied with `security.protect()` reaches the file through these bytes — nothing on disk changes until you write them somewhere.

- Kind: method
- Since: 1.0.0

Returns `Promise<Uint8Array>`: The document's bytes.

Throws:

- `FEATURE_NOT_LICENSED` — the license lacks `export`.
- `INVALID_STATE` — a progressive document is still downloading.
- `EXPORT_FAILED` — a changed PDF/A file's claim cannot be removed.
- `DOCUMENT_CLOSED` — the document has been closed.

```ts
const bytes = await doc.save();
// .slice() gives an ArrayBuffer-backed copy, which TypeScript 5.7+ requires of a request body.
await fetch('/upload', { method: 'PUT', body: bytes.slice() });
```

Part of [PDFDocument](https://kernstra.com/docs/web-sdk/api/pdfdocument) in the Kernstra Web SDK 1.0.0 API reference.

Web page: https://kernstra.com/docs/web-sdk/api/pdfdocument/save
