---
title: "Headless link annotations | Nutrient Web SDK"
canonical_url: "https://www.nutrient.io/guides/web/headless/link/"
md_url: "https://www.nutrient.io/guides/web/headless/link.md"
last_updated: "2026-05-15T19:10:05.084Z"
description: "Build link annotations with every PDF action type, URI, GoTo, JavaScript, Launch, Hide, Reset, Submit, programmatically with Nutrient Web SDK, without the default link editor UI."
---

# Headless link annotations

A `LinkAnnotation` is a clickable region on a PDF page paired with an [`Action`](https://www.nutrient.io/api/web/modules/NutrientViewer.Actions.html). The default link editor handles the common case — internal navigation and external URLs — but the SDK supports every PDF action type the specification defines. Build links programmatically when you need an action type the editor doesn’t expose, when you’re importing link metadata from a server, or when the link needs to be created in response to a workflow rather than a user click.

Looking for the visual side of this? See the `annotations.link` [slot](https://www.nutrient.io/guides/web/user-interface/ui-customization/supported-slots.md#annotations) for replacing the link editor that appears when the user creates or edits a link annotation. This page covers the programmatic surface you’ll call from inside that custom UI.

## When to use this

Reach for the headless link API when you’re:

- Importing link metadata from a backend — for example, marking up a generated PDF with cross-references that follow a known schema.

- Creating links with action types the default editor doesn’t expose, such as form submission or JavaScript actions.

- Building a custom link editor that walks the user through every action type with your own labels and validation.

- Bulk-creating links across multiple pages from a single workflow.

## Action types

Every link annotation has an `action` property. The action determines what happens when the link is clicked.

| Action class                            | Use case                                                                 |
| --------------------------------------- | ------------------------------------------------------------------------ |
| [`URIAction`](https://www.nutrient.io/api/web/classes/NutrientViewer.Actions.URIAction.html)               | External URL or Nutrient-specific scheme.                                |
| [`GoToAction`](https://www.nutrient.io/api/web/classes/NutrientViewer.Actions.GoToAction.html)             | Jump to another page or position within the current document.            |
| [`JavaScriptAction`](https://www.nutrient.io/api/web/classes/NutrientViewer.Actions.JavaScriptAction.html) | Run a JavaScript expression. Subject to the SDK’s scripting permissions. |
| [`LaunchAction`](https://www.nutrient.io/api/web/classes/NutrientViewer.Actions.LaunchAction.html)         | Launch an external application or open an embedded file.                 |
| [`HideAction`](https://www.nutrient.io/api/web/classes/NutrientViewer.Actions.HideAction.html)             | Hide or show one or more form fields by name.                            |
| [`ResetFormAction`](https://www.nutrient.io/api/web/classes/NutrientViewer.Actions.ResetFormAction.html)       | Reset form fields to their default values.                               |
| [`SubmitFormAction`](https://www.nutrient.io/api/web/classes/NutrientViewer.Actions.SubmitFormAction.html)     | Submit form data to a URL.                                               |

All action classes live under [`NutrientViewer.Actions`](https://www.nutrient.io/api/web/modules/NutrientViewer.Actions.html).

## Example: A link to another page

This is the common case, that of a link that jumps to a target page in the same document:

```js

const { LinkAnnotation } = NutrientViewer.Annotations;
const { GoToAction } = NutrientViewer.Actions;
const { Rect } = NutrientViewer.Geometry;

const link = new LinkAnnotation({
  pageIndex: 0,
  boundingBox: new Rect({ left: 100, top: 100, width: 200, height: 24 }),
  action: new GoToAction({ pageIndex: 4 })
});

await instance.create(link);

```

## Example: A link to an external URL

```js

const { URIAction } = NutrientViewer.Actions;

const link = new LinkAnnotation({
  pageIndex: 0,
  boundingBox: new Rect({ left: 100, top: 200, width: 200, height: 24 }),
  action: new URIAction({ uri: "https://www.nutrient.io/" })
});

await instance.create(link);

```

## Example: A JavaScript action

JavaScript actions run a JavaScript expression when the link is clicked. They’re powerful but constrained, they only run when the SDK’s scripting support is enabled, and they’re sandboxed to the document context:

```js

const { JavaScriptAction } = NutrientViewer.Actions;

const link = new LinkAnnotation({
  pageIndex: 0,
  boundingBox: new Rect({ left: 100, top: 250, width: 200, height: 24 }),
  action: new JavaScriptAction({
    script: "app.alert('Hello from a PDF action.');"
  })
});

await instance.create(link);

```

## Example: A form-control action

Use `ResetFormAction`, `SubmitFormAction`, or `HideAction` to drive form workflows from a click. The example below resets the named form fields when the link is clicked:

```js

const { ResetFormAction } = NutrientViewer.Actions;
const { List } = NutrientViewer.Immutable;

const link = new LinkAnnotation({
  pageIndex: 0,
  boundingBox: new Rect({ left: 100, top: 300, width: 200, height: 24 }),
  action: new ResetFormAction({
    fields: List(["name", "email", "phone"])
  })
});

await instance.create(link);

```

`HideAction` follows the same pattern but takes a `hide` Boolean alongside the field list. `SubmitFormAction` takes a `uri` and an `includeExclude` field set.

## Example: Bulk-creating links from a server-side schema

When the link metadata comes from a server, build the action class dynamically from the schema and reuse a single create call:

```js

const links = [
  { page: 0, x: 100, y: 100, type: "uri", uri: "https://www.nutrient.io/" },
  { page: 0, x: 100, y: 150, type: "goto", target: 5 },
  { page: 1, x: 200, y: 100, type: "javascript", script: "console.log('clicked');" }
];

const annotations = links.map((data) => {
  let action;
  switch (data.type) {
    case "uri":
      action = new NutrientViewer.Actions.URIAction({ uri: data.uri });
      break;
    case "goto":
      action = new NutrientViewer.Actions.GoToAction({ pageIndex: data.target });
      break;
    case "javascript":
      action = new NutrientViewer.Actions.JavaScriptAction({ script: data.script });
      break;
  }

  return new NutrientViewer.Annotations.LinkAnnotation({
    pageIndex: data.page,
    boundingBox: new NutrientViewer.Geometry.Rect({
      left: data.x,
      top: data.y,
      width: 200,
      height: 24
    }),
    action
  });
});

await instance.create(annotations);

```

## Customizing click behavior

Listen for `annotations.press` to intercept link clicks before the SDK runs the action:

```js

instance.addEventListener("annotations.press", (event) => {
  if (event.annotation instanceof NutrientViewer.Annotations.LinkAnnotation) {
    const action = event.annotation.action;
    if (action instanceof NutrientViewer.Actions.URIAction) {
      const ok = window.confirm(`Open ${action.uri}?`);
      if (!ok) {
        event.preventDefault();
      }
    }
  }
});

```

## Related

- [Color presets](https://www.nutrient.io/guides/web/headless/color-presets.md) — Read link annotation color presets for a custom picker.

- [Link annotations reference](https://www.nutrient.io/api/web/classes/NutrientViewer.Annotations.LinkAnnotation.html) — The `LinkAnnotation` class details.

- [PDF actions support](https://www.nutrient.io/guides/web/annotations/pdf-actions.md) — The broader story for PDF action handling.
---

## Related pages

- [Headless callout annotations](/guides/web/headless/callout.md)
- [Headless color presets](/guides/web/headless/color-presets.md)
- [Headless image annotations](/guides/web/headless/image.md)
- [Annotation clipboard](/guides/web/headless/clipboard.md)
- [Headless](/guides/web/headless.md)
- [Headless ink annotations](/guides/web/headless/ink.md)
- [Headless stamp annotations](/guides/web/headless/stamp.md)
- [Headless note annotations](/guides/web/headless/note.md)
- [Redactions from text selection](/guides/web/headless/redactions-from-selection.md)
- [Programmatic notes panel](/guides/web/headless/notes-panel.md)
- [Headless text annotations](/guides/web/headless/text-annotations.md)
- [Headless shape annotations](/guides/web/headless/shape.md)
- [Headless text markup](/guides/web/headless/text-markup.md)

