---
title: "Link plugin"
description: "Add hyperlinks to content."
canonical_url: "https://www.tiny.cloud/docs/tinymce/latest/link/"
md_url: "https://www.tiny.cloud/docs/tinymce/latest/link/index.md"
version: "latest"
last_updated: "2026-03-16T11:48:27Z"
tokens: 5384
---
# Link plugin

The **link** plugin allows a user to link external resources such as website URLs, to selected text in their document.

It adds two toolbar buttons called `link` and `unlink` and three menu items called `link`, `unlink` and `openlink`. The toolbar button and menu item called `link` are included in TinyMCE’s default configuration. The `link` menu item can be found in the `Insert` menu.

The **link** plugin also includes a context menu and context toolbar. The context toolbar can be configured using the [`link_context_toolbar`](#link_context_toolbar) and [`link_quicklink`](#link_quicklink) options documented below.

## Basic setup

```js
tinymce.init({
  selector: 'textarea',  // change this value according to your HTML
  plugins: 'link',
  toolbar: 'link'
});
```

> **Note:** For information on bundling this plugin with module bundlers, see [Bundling TinyMCE - Overview](../bundling-guide/).

## Options

These settings affect the execution of the `link` plugin. Predefined links, targets, and more can be specified here.

### `link_default_target`

This option allows you to set a default `target` value for links when inserting/editing a link via the link dialog. If the value of `link_default_target` matches a value specified by the [`link_target_list`](#link_target_list) option, that item will be set as the default item for the targets dropdown in the link dialog.

> **Note:** This option also applies to the [autolink](../autolink/) plugin.
**Type:** `String`

#### Example: using `link_default_target`

```js
tinymce.init({
  selector: 'textarea',  // change this value according to your HTML
  plugins: 'link',
  toolbar: 'link',
  link_default_target: '_blank'
});
```

### `link_assume_external_targets`

Set whether TinyMCE should prepend a `http://` prefix if the supplied URL does not contain a protocol prefix.

- `false`: Users are prompted to prepend `http://` when the URL entered starts with `www` and does not have a protocol. Other URLs are added without prompt.
- `true`: URLs are assumed to be external. Users are prompted to prepend a `http://` prefix when the protocol is not specified.
- `'http'`: URLs are assumed to be external. URLs without a protocol prefix are prepended a `http://` prefix.
- `'https'`: URLs are assumed to be external. URLs without a protocol prefix are prepended a `https://` prefix.

**Type:** `Boolean` or `String`

**Default value:** `false`

**Possible values:** `true`, `false`, `'http'`, `'https'`

#### Example: using `link_assume_external_targets`

```js
tinymce.init({
  selector: 'textarea',  // change this value according to your HTML
  plugins: 'link',
  toolbar: 'link',
  link_assume_external_targets: true
});
```

### `link_class_list`

The `link_class_list` option allows you to specify a list of classes for the link dialog. These classes will appear in a dropdown menu in the link dialog. Each class must be defined as an object with a `title` and a `value`. For example: `{ title: 'Cat', value: 'cat' }`. When the dialog is submitted, the `value` of the selected class item from the dropdown will be set as the link’s `class`.

**Type:** `Array`

**Default value:** `[]`

#### Example: using `link_class_list`

```js
tinymce.init({
  selector: 'textarea',  // change this value according to your HTML
  plugins: 'link',
  toolbar: 'link',
  link_class_list: [
    { title: 'None', value: '' },
    { title: 'External Link', value: 'ext_link' },
    { title: 'Internal Support Link', value: 'int_sup_link' },
    { title: 'Internal Marketing Link', value: 'int_mark_link' },
    { title: 'Other Internal Link', value: 'int_other_link' }
  ]
});
```

#### Example of a nested list of link classes

To create a nested list, replace `value` with `menu` to add the top level of the list, then provide an array of items.

For example:

```js
tinymce.init({
  selector: 'textarea',  // change this value according to your HTML
  plugins: 'link',
  toolbar: 'link',
  link_class_list: [
    { title: 'None', value: '' },
    { title: 'External Link', value: 'ext_link' },
    { title: 'Internal Links',
      menu: [
        { title: 'Internal Support Link', value: 'int_sup_link' },
        { title: 'Internal Marketing Link', value: 'int_mark_link' },
        { title: 'Other Internal Link', value: 'int_other_link' }
      ]
    }
  ]
});
```

### `link_context_toolbar`

By default it is not possible to open links directly from the editor. Setting `link_context_toolbar` to `true` will enable a context toolbar that will appear when the user’s cursor is within a link. This context toolbar contains fields to modify, remove and open the selected link. External links will be opened in a separate tab, while relative links scroll to a target within the editor (if the target is found).

> **Note:** This context toolbar is the same as the context toolbar mentioned in the [Link plugin - `link_quicklink`](#link_quicklink) documentation.
**Type:** `Boolean`

**Default value:** `false`

**Possible values:** `true`, `false`

#### Example: using `link_context_toolbar`

```js
tinymce.init({
  selector: 'textarea',  // change this value according to your HTML
  plugins: 'link',
  toolbar: 'link',
  link_context_toolbar: true
});
```

### `link_default_protocol`

This option allows you to set a default protocol for links when inserting/editing a link via the link dialog. The protocol will apply to any links where the protocol has not been specified and the prefix prompt has been accepted.

> **Note:** This option also applies to the [autolink](../autolink/) plugin.
**Type:** `String`

**Default value:** `'https'`

#### Example: using `link_default_protocol`

```js
tinymce.init({
  selector: 'textarea',  // change this value according to your HTML
  plugins: 'link',
  toolbar: 'link',
  link_default_protocol: 'http'
});
```

### `link_list`

This option lets you specify a predefined list of links for the link dialog. These links are added to a drop-down list in the link dialog. When a list item is selected, the dialog will be populated with the relevant data. This is useful if your users need to regularly link to the same sources.

There are multiple ways to specify how to get the data for the link list, but all methods rely on the returned data containing an array of link items. A link item is an object with a `title` and a `value`. For example: `{ title: 'My page 1', value: 'https://www.tiny.cloud' }`.

**Type:** `String`, `Array` or `Function`

#### Example of an array of link items

```js
tinymce.init({
  selector: 'textarea',  // change this value according to your HTML
  plugins: 'link',
  toolbar: 'link',
  link_list: [
    { title: '{companyname} Home Page', value: '{companyurl}' },
    { title: '{companyname} Blog', value: '{companyurl}/blog' },
    { title: '{productname} Documentation', value: '{companyurl}/docs/' },
    { title: '{productname} on Stack Overflow', value: '{communitysupporturl}' },
    { title: '{productname} GitHub', value: 'https://github.com/tinymce/' }
  ]
});
```

#### Example of a nested list of link items

To create a nested list, replace `value` with `menu` to add the top level of the list, then provide an array of items.

For example:

```js
tinymce.init({
  selector: 'textarea',  // change this value according to your HTML
  plugins: 'link',
  toolbar: 'link',
  link_list: [
    { title: '{companyname} Home Page', value: '{companyurl}' },
    { title: '{companyname} Blog', value: '{companyurl}/blog' },
    { title: '{productname} Support resources',
      menu: [
        { title: '{productname} Documentation', value: '{companyurl}/docs/' },
        { title: '{productname} on Stack Overflow', value: '{communitysupporturl}' },
        { title: '{productname} GitHub', value: 'https://github.com/tinymce/' }
      ]
    }
  ]
});
```

#### Example of an external script that returns a JSON array of link items

You can also configure a URL with JSON data. The JSON data must use the same format as above.

```js
tinymce.init({
  selector: 'textarea',  // change this value according to your HTML
  plugins: 'link',
  toolbar: 'link',
  link_list: '/mylist.php'
});
```

#### Example of a custom asynchronous callback function

`link_list` can also take a function that is called when the link dialog is opened. TinyMCE passes this function a `success` callback function, which should be passed an array of link items. This allows for asynchronous and dynamic generation of the list of links.

The following is an example of how `link_list` can be used with a callback function. `fetchLinkList` could be replaced with any function that returns an array of link items. It can be used to generate a list of link items based on:

- Data retrieved from a database.
- The current editor content.
- The current user.

```js
const fetchLinkList = () => [
  { title: 'My page 1', value: 'https://www.tiny.cloud' },
  { title: 'My page 2', value: 'https://about.tiny.cloud' }
];

tinymce.init({
  selector: 'textarea',  // change this value according to your HTML
  plugins: 'link',
  toolbar: 'link',
  link_list: (success) => { // called on link dialog open
    const links = fetchLinkList(); // get link_list data
    success(links); // pass link_list data to {productname}
  }
});
```

### `link_title`

This options allows you disable the link `title` input field in the `link` dialog.

**Type:** `Boolean`

**Default value:** `true`

**Possible values:** `true`, `false`

#### Example: using `link_title`

```js
tinymce.init({
  selector: 'textarea',  // change this value according to your HTML
  plugins: 'link',
  toolbar: 'link',
  link_title: false
});
```

### `link_quicklink`

This option changes the behaviour of the `CTRL + K` shortcut and the [`mceLink`](#mceLink) command.

When `link_quicklink` is set to `false`, pressing `CTRL + K` or executing the `mceLink` command will open the Link dialog.

When `link_quicklink` is set to `true`, pressing `CTRL + K` will open the link context toolbar instead, though the Link dialog can still be opened by running `editor.execCommand('mceLink', false, { dialog: true })`.

When a link is selected, the link context toolbar contains fields and buttons for modifying, removing and opening the selected link. When the selection doesn’t contain a link, the link context toolbar contains fields and buttons for quickly inserting a link.

> **Note:** This context toolbar is the same as the context toolbar mentioned in the [`link_context_toolbar`](#link_context_toolbar) documentation above.
**Type:** `Boolean`

**Default value:** `false`

**Possible values:** `true`, `false`

#### Example: using `link_quicklink`

```js
tinymce.init({
  selector: 'textarea',  // change this value according to your HTML
  plugins: 'link',
  toolbar: 'link',
  link_quicklink: true
});
```

### `link_rel_list`

This option lets you specify a list of `rel` values for the `link` dialog. These values gets applied to the `rel` attribute. Each `rel` item must be defined as an object with a `title` and a `value`. For example: `{ title: 'No Referrer', value: 'noreferrer' }`. When the dialog is submitted, the `value` of the selected `rel` item will be set as the link’s `rel` attribute.

**Type:** `Array`

**Default value:** `[]`

#### Example: using `link_rel_list`

```js
tinymce.init({
  selector: 'textarea',  // change this value according to your HTML
  plugins: 'link',
  toolbar: 'link',
  link_rel_list: [
    { title: 'No Referrer', value: 'noreferrer' },
    { title: 'External Link', value: 'external' }
  ]
});
```

### `link_target_list`

The `link_target_list` option lets you specify a list of named targets for the `link` dialog. These targets will appear in a dropdown menu in the link dialog. Each target must be defined as an object with a `title` and a `value`. For example: `{ title: 'Same page', value: '_self' }`. When the dialog is submitted, the `value` of the selected target item will be set as the link’s `target` attribute.

If [`link_default_target`](#link_default_target) is also configured and its value matches a value specified by `link_target_list`, that item will be set as the default item for the targets dropdown in the link dialog.

**Type:** `Boolean` or `Array`

**Possible values:** `true+, +false+, +_blank`, `_self`, `_parent`, `_blank`

**Default value:**

```js
[
  { text: 'Current window', value: '' },
  { text: 'New window', value: '_blank' }
]
```

#### Example: adding a `_parent` target to the dropdown list

```js
tinymce.init({
  selector: 'textarea',  // change this value according to your HTML
  plugins: 'link',
  toolbar: 'link',
  link_target_list: [
    { title: 'None', value: '' },
    { title: 'Same page', value: '_self' },
    { title: 'New page', value: '_blank' },
    { title: 'Parent frame', value: '_parent' }
  ]
});
```
To disable the option dialog, set `link_target_list` to `false`.

#### Example: turning off the target list dialog

```js
tinymce.init({
  selector: 'textarea',  // change this value according to your HTML
  plugins: 'link',
  toolbar: 'link',
  link_target_list: false
});
```

### `link_attributes_postprocess`

This option allows overriding attributes of an inserted link.

**Type:** `Function`

**Default value:** `undefined`

#### Example: using `link_attributes_postprocess`

```js
tinymce.init({
  selector: 'textarea', // change this value according to your HTML
  plugins: 'link',
  toolbar: 'link',
  link_attributes_postprocess: (attrs) => {
    console.log(attrs);
    if (attrs.rel) {
      attrs.rel += 'noreferrer';
    }
  }
});
```

### `files_upload_handler`

This option specifies a function that handles file uploads in the link dialog’s upload tab. This is similar to [`images_upload_handler`](../file-image-upload/#images_upload_handler), but is specifically designed for document and file uploads.

The upload handler function takes two arguments:

- `blobInfo` - An object containing information about the file blob to upload
- A `progress` callback that takes a value between 1 and 100

and returns a [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) that will resolve with an object containing the uploaded file `url` and `fileName`, or reject with an error. The resolved object must have the following structure:

- `url` - The URL of the uploaded file
- `fileName` - The filename of the uploaded file

The error can be either a string or an object containing the following properties:

- `message` - The error message to display in the UI.
- `remove` - A flag to remove the file from the document, defaults to `false` if not set.

When both `files_upload_handler` and [`documents_file_types`](#documents_file_types) are configured, the link dialog displays an "Upload" tab that enables file uploads via the function defined by `files_upload_handler`.

**Type:** `Function`

**Default value:** `undefined`

#### Example: using `files_upload_handler`

This example shows a client-side JavaScript handler that uploads files to a server endpoint. The server should return a JSON response with a `location` property containing the URL of the uploaded file.

```js
const files_upload_handler = (blobInfo, progress) => new Promise((resolve, reject) => {
  const xhr = new XMLHttpRequest();
  xhr.withCredentials = false;
  xhr.open('POST', 'upload-handler.php');

  xhr.upload.onprogress = (e) => {
    progress(e.loaded / e.total * 100);
  };

  xhr.onload = () => {
    if (xhr.status === 403) {
      reject({ message: 'HTTP Error: ' + xhr.status, remove: true });
      return;
    }

    if (xhr.status < 200 || xhr.status >= 300) {
      reject('HTTP Error: ' + xhr.status);
      return;
    }

    const json = JSON.parse(xhr.responseText);

    if (!json || typeof json.location != 'string') {
      reject('Invalid JSON: ' + xhr.responseText);
      return;
    }

    resolve({
      url: json.location,
      fileName: blobInfo.filename()
    });
  };

  xhr.onerror = () => {
    reject('File upload failed due to a XHR Transport error. Code: ' + xhr.status);
  };

  const formData = new FormData();
  formData.append('file', blobInfo.blob(), blobInfo.filename());

  xhr.send(formData);
});

tinymce.init({
  selector: 'textarea',
  plugins: 'link',
  toolbar: 'link',
  files_upload_handler: files_upload_handler,
  documents_file_types: [
    { mimeType: 'application/pdf', extensions: [ 'pdf' ] },
    { mimeType: 'application/msword', extensions: [ 'doc' ] },
    { mimeType: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', extensions: [ 'docx' ] },
    { mimeType: 'text/plain', extensions: [ 'txt' ] }
  ]
});
```

> **Note:** **Server-Side Handler Requirements**
> 
> The server endpoint (e.g., `upload-handler.php` in the example above) should:
> 
> - Accept a POST request with a file in the request body (sent as FormData with the field name `file`)
> - Return a JSON response with a `location` property containing the URL of the uploaded file: `{ "location": "<path-to-your-web-server>/uploaded/file.pdf" }`
> - Handle errors by returning appropriate HTTP status codes (e.g., 403 for forbidden file types, 400 for invalid requests, 500 for server errors)
> - Set appropriate CORS headers if needed for cross-origin requests
> This is similar to how [`images_upload_url`](../file-image-upload/#images_upload_url) works, but `files_upload_handler` gives you full control over the client-side upload logic, including custom error handling, progress tracking, and request customization.

### `documents_file_types`

This option specifies which file types (MIME types and extensions) are supported for file uploads in the link dialog. When both the [Link](#) plugin and the [`files_upload_handler`](#files_upload_handler) are configured, the link dialog displays an "Upload" tab that enables file uploads.

The option should be an array of objects, where each object contains:

- `mimeType` - A string representing the MIME type (e.g., `'application/pdf'`)
- `extensions` - An array of strings representing the file extensions (e.g., `['pdf']`)

**Type:** `Array`

**Default value:** `undefined`

> **Note:** **Priority Behavior**
> 
> When `documents_file_types` is set, it acts as the source of truth for supported file types throughout the editor. This means:
> 
> - The Link plugin uses this custom list instead of its default supported file types
> If `documents_file_types` is not set:
> 
> - The Link plugin uses its default list of supported file types

#### Example: using `documents_file_types`

```js
tinymce.init({
  selector: 'textarea',
  plugins: 'link',
  toolbar: 'link',
  // Configure the file upload handler to handle the file uploads
  files_upload_handler: async (blobInfo, progress) => {
    return { url: 'https://example.com/file.pdf', fileName: 'file.pdf' };
  },
  // Configure the list of supported file types
  documents_file_types: [
    { mimeType: 'application/msword', extensions: [ 'doc' ] },
    { mimeType: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', extensions: [ 'docx' ] },
    { mimeType: 'application/pdf', extensions: [ 'pdf' ] },
    { mimeType: 'text/plain', extensions: [ 'txt' ] }
  ]
});
```

### `link_uploadtab`

This option controls whether the "Upload" tab is displayed in the link dialog. The upload tab enables file uploads when both [`files_upload_handler`](#files_upload_handler) and [`documents_file_types`](#documents_file_types) are configured.

If set to `false`, the upload tab will be hidden even if the other two options are set.

**Type:** `Boolean`

**Default value:** `true`

**Possible values:** `true`, `false`

#### Example: hiding the link dialog upload tab

```js
tinymce.init({
  selector: 'textarea',
  plugins: 'link',
  toolbar: 'link',
	files_upload_handler: (blobInfo, _progress) => new Promise((success) => {
	  setTimeout(() => {
		success({ url: 'https://www.google.com/logos/google.jpg', fileName: 'test-in-demo' });
	  }, 2_000);
	}),
  documents_file_types: [
    { mimeType: 'application/pdf', extensions: [ 'pdf' ] }
  ],
  link_uploadtab: false  // Hide the link dialog upload tab
});
```

## Toolbar buttons

The Link plugin provides the following toolbar buttons:

| Toolbar button identifier | Description |
| --- | --- |
| `link` | Creates/Edits links within the editor. |
| `openlink` | Opens the selected link in a new tab. |
| `unlink` | Removes links from the current selection. |

These toolbar buttons can be added to the editor using:

- The [`toolbar`](../toolbar-configuration-options/#toolbar) configuration option.
- The [`quickbars_insert_toolbar`](../quickbars/#quickbars_insert_toolbar) configuration option.
- [Custom Context toolbars](../contexttoolbar/).

## Menu items

The Link plugin provides the following menu items:

| Menu item identifier | [Default Menu Location](../menus-configuration-options/#example-the-tinymce-default-menu-items) | Description |
| --- | --- | --- |
| `link` | Insert | Opens the link dialog. |
| `openlink` | *Not Applicable* | Opens the selected link in a new tab. |
| `unlink` | *Not Applicable* | Removes the hyperlink from the selected text. |

These menu items can be added to the editor using:

- The [`menu`](../menus-configuration-options/#menu) configuration option.
- The [`contextmenu`](../menus-configuration-options/#contextmenu) configuration option.
- [Custom Menu toolbar buttons](../custom-menu-toolbar-button/).

## Commands

The Link plugin provides the following TinyMCE command.

| Command | Description |
| --- | --- |
| mceLink | Opens the Link dialog or the link context toolbar at the current cursor position or for the current selection. The behaviour depends on the [`link_quicklink`](#link_quicklink) option. Pass `{ dialog: true }` as the third argument to always open the full Link dialog, even when `link_quicklink` is enabled. |

Example: open link dialog or context toolbar (default behaviour)
```js
tinymce.activeEditor.execCommand('mceLink');
```
Example: always open the full Link dialog
```js
tinymce.activeEditor.execCommand('mceLink', false, { dialog: true });
```
