---
title: "The LinkHandler API"
manual: "TYPO3 Explained"
version: "11.5"
permalink: "https://docs.typo3.org/permalink/t3coreapi:linkhandler@11.5"
source: "ApiOverview/LinkHandling/Linkhandler/Index.rst"
rendered: "2026-10-21T15:30:00+00:00"
---

> [!WARNING]
> **Attention**
>
> TYPO3 v11 has reached end-of-life as of October 31th 2024 and
> is no longer being maintained. Use the version switcher on the top
> left of this page to select documentation for a supported version of TYPO3.
>
> Need more time before upgrading?
> You can purchase Extended Long Term Support (ELTS) for TYPO3 v11 here:
> [TYPO3 ELTS](https://typo3.com/services/extended-support-elts).

# The LinkHandler API {#linkhandler}

The LinkHandler API currently consists of 7 LinkHandler classes and the
`\TYPO3\CMS\Recordlist\LinkHandler\LinkHandlerInterface`. The
LinkHandlerInterface can be implemented to create custom LinkHandlers.

Most LinkHandlers cannot receive additional configuration, they are marked as
`@internal` and contain neither hooks nor events. They are therefore
of interest to Core developers only.

Current LinkHandlers:

-   [The PageLinkHandler](https://docs.typo3.org/permalink/t3coreapi:pagelinkhandler@11.5): for linking pages and content
-   [The RecordLinkHandler](https://docs.typo3.org/permalink/t3coreapi:recordlinkhandler@11.5): for linking any kind of record
-   UrlLinkHandler: for linking external urls
-   FileLinkHandler: for linking files in the [File abstraction layer (FAL)](https://docs.typo3.org/permalink/t3coreapi:fal@11.5)
-   FolderLinkHandler: for linking to directories
-   MailLinkHandler: for linking mail
-   TelephoneLinkHandler: for linking phone numbers

> [!NOTE]
> In the system extension `core` there are also classes ending on
> "LinkHandler". However those implement the `interface LinkHandlingInterface`
> and are part of the LinkHandling API, not the LinkHandler API.

The following LinkHandlers are of interest:

-   [The PageLinkHandler](https://docs.typo3.org/permalink/t3coreapi:the-pagelinkhandler@11.5)
-   [The RecordLinkHandler](https://docs.typo3.org/permalink/t3coreapi:the-recordlinkhandler@11.5)
-   [Implementing a custom LinkHandler](https://docs.typo3.org/permalink/t3coreapi:implementing-a-custom-linkhandler@11.5)

The links are now stored in the database with the syntax
`<a href="t3://record?identifier=anIdentifier&amp;uid=456">A link</a>`.

1.  TypoScript is used to generate the actual link in the frontend.

    ```typoscript
    config.recordLinks.anIdentifier {
        // Do not force link generation when the record is hidden
        forceLink = 0
        typolink {
            parameter = 123
            additionalParams.data = field:uid
            additionalParams.wrap = &tx_example_pi1[item]=|&tx_example_pi1[controller]=Item&tx_example_pi1[action]=show
        }
    }
    ```

    > [!IMPORTANT]
    > Do not change the identifier after links have been created  using the LinkHandler. The identifier will be
    > stored as part of the link in the database.

## LinkHandler page TSconfig options {#linkhandler-pagetsconfig}

The minimal page TSconfig configuration is:

**EXT:some_extension/Configuration/page.tsconfig**

```typoscript
TCEMAIN.linkHandler.anIdentifier {
    handler = TYPO3\CMS\Recordlist\LinkHandler\RecordLinkHandler
    label = LLL:EXT:extension/Resources/Private/Language/locallang.xlf:link.customTab
    configuration {
        table = tx_example_domain_model_item
    }
}
```

See [Link handler configuration](https://docs.typo3.org/permalink/t3coreapi:link-handler-configuration@11.5) for all available options.

### Example: news records from one storage pid {#example-news-records-from-one-storage-pid}

The following configuration hides the page tree and shows news records only
from the defined storage page:

**EXT:some_extension/Configuration/page.tsconfig**

```typoscript
TCEMAIN.linkHandler.news {
    handler = TYPO3\CMS\Recordlist\LinkHandler\RecordLinkHandler
    label = News
    configuration {
        table = tx_news_domain_model_news
        storagePid = 123
        hidePageTree = 1
    }
    displayAfter = mail
}
```

It is possible to have another configuration using another storagePid which
also contains news records.

This configuration shows a reduced page tree starting at page with uid 42:

**EXT:some_extension/Configuration/page.tsconfig**

```typoscript
TCEMAIN.linkHandler.bookreports {
    handler = TYPO3\CMS\Recordlist\LinkHandler\RecordLinkHandler
    label = Book Reports
    configuration {
        table = tx_news_domain_model_news
        storagePid = 42
        pageTreeMountPoints = 42
        hidePageTree = 0
    }
}
```

The PageTSconfig of the LinkHandler is being used in sysext `recordlist`
in class `\TYPO3\CMS\Recordlist\LinkHandler\RecordLinkHandler`
which does not contain Hooks or Slots.

## LinkHandler TypoScript options {#linkhandler-typoscript}

A configuration could look like this:

**EXT:some_extension/Configuration/TypoScript/setup.typoscript**

```typoscript
config.recordLinks.anIdentifier {
    forceLink = 0

    typolink {
        parameter = 123
        additionalParams.data = field:uid
        additionalParams.wrap = &tx_example_pi1[item]=|
    }
}
```

The TypoScript Configuration of the LinkHandler is being used in sysext `frontend`
in class `\TYPO3\CMS\Frontend\Typolink\DatabaseRecordLinkBuilder`.

### Example: news records displayed on fixed detail page {#example-news-records-displayed-on-fixed-detail-page}

The following displays the link to the news on a detail page:

**EXT:some_extension/Configuration/TypoScript/setup.typoscript**

```typoscript
config.recordLinks.news {
   typolink {
      parameter = 123
      additionalParams.data = field:uid
      additionalParams.wrap = &tx_news_pi1[controller]=News&tx_news_pi1[action]=detail&tx_news_pi1[news]=|
   }
}
```

Once more if the book reports that are also saved as `tx_news_domain_model_news` record should be displayed on their own
detail page you can do it like this:

**EXT:some_extension/Configuration/TypoScript/setup.typoscript**

```typoscript
config.recordLinks.bookreports  {
   typolink {
      parameter = 987
      additionalParams.data = field:uid
      additionalParams.wrap = &tx_news_pi1[controller]=News&tx_news_pi1[action]=detail&tx_news_pi1[news]=|
   }
}
```
