---
title: "Quick start"
description: "Open a PDF, render its first page, read and search its text, highlight a match and save the result."
source: "https://www.embedpdf.com/docs/engine/quick-start"
---

# Quick start

This guide opens a PDF, shows its first page, searches it, highlights a match and saves the
result.

## 1. Install

```sh
pnpm add @embedpdf/engine@next
```

## 2. Create the engine

Create one engine for your whole app and reuse it.

```ts
import { localEngine } from '@embedpdf/engine';

const engine = localEngine();
```

Creating it is instant. The engine starts PDFium in a Web Worker the first time you use it, so
you don't have to wait for anything here.

## 3. Open a PDF

Give the engine the file's bytes. Here we fetch them from a URL; a file the user picked works
the same way (`await file.arrayBuffer()`).

```ts
const response = await fetch('/invoice.pdf');
const doc = await engine.open({ kind: 'bytes', bytes: await response.arrayBuffer() });
```

`doc` is your handle to the open document. Everything else starts from it.

## 4. Show the first page

List the pages, then render the first one as an image:

```ts
const { pages } = await doc.pages.list();
const firstPage = doc.page(pages[0].ref);

const image = await firstPage.render.image({ viewport: { kind: 'width', width: 800 } });
const { url } = await image.objectUrl();

document.querySelector('img')!.src = url;
```

Each page has a `ref`: its address in the document. `doc.page(ref)` gives you a handle for that
page, and you pass the same `ref` to anything that works on pages.

## 5. Read the text

```ts
const { text } = await firstPage.text.get();
console.log(text);
```

## 6. Search

Search the whole document. Each match says which page it's on and where it is:

```ts
const { matches } = await doc.search.query({ text: 'total' });

console.log(`${matches.length} matches`);
```

## 7. Highlight a match

A match carries one `segment` per line it covers, each with the four corners of that piece of
text. A highlight takes exactly those corners:

```ts
const match = matches[0];

await doc.page(match.page).annotations.create({
  subtype: 'highlight',
  quadPoints: match.segments.map((segment) => segment.quad),
  color: '#ffd700',
});
```

Render the page again and the highlight is there. See
[Highlights & text markup](https://www.embedpdf.com/docs/engine/annotations/text-markup) for underlines, strikeouts and
the other fields.

## 8. Save

`download()` returns the PDF with your changes, as bytes:

```ts
const bytes = await doc.download();
```

To let the user save it, wrap the bytes in a `Blob`:

```ts
const link = document.createElement('a');
link.href = URL.createObjectURL(new Blob([bytes], { type: 'application/pdf' }));
link.download = 'invoice-highlighted.pdf';
link.click();
```

## 9. Clean up

Close the document when you're done with it. Keep the engine for the next one.

```ts
await doc.close();
```

> Every call returns a promise you can cancel: keep it and call `.abort()`, for example
> when the user scrolls past a page before its image arrives. See [Errors &
> cancelling](https://www.embedpdf.com/docs/engine/concepts/errors-and-cancelling).

## Next steps

- [Setup](https://www.embedpdf.com/docs/engine/setup) — Bundlers, workers, server-side rendering and fonts.
- [Annotations](https://www.embedpdf.com/docs/engine/annotations) — Every kind of annotation, and how to change them.
- [Selection & geometry](https://www.embedpdf.com/docs/engine/text/selection-and-geometry) — Find the text under the pointer and draw your own selection.
