---
title: "Generating URLs with the UriBuilder"
manual: "TYPO3 Explained"
version: "main"
permalink: "https://docs.typo3.org/permalink/t3coreapi:uri-builder-api@main"
source: "ExtensionArchitecture/Extbase/Routing/UriBuilder.rst"
rendered: "2026-09-20T15:52:37+00:00"
---

# Generating URLs with the `UriBuilder` {#uri-builder-api}

The `UriBuilder` generates URLs
for Extbase actions. When routing configuration is in place, it produces the
clean URL defined by the matching route variant. Without routing configuration
it produces the raw namespaced query string.

The UriBuilder is available in two contexts: inside a controller action via
`$this->uriBuilder`, and inside Fluid templates via `<f:link.action>`
and `<f:uri.action>`.

## Generating URLs in a controller action {#extbase-uri-builder-other}

Use `uriFor()` to generate a URL for any action. It is available as
`$this->uriBuilder->uriFor()` in any controller action:

**EXT:my_extension/Classes/Controller/ConferenceController.php**

```php
<?php

namespace MyVendor\MyExtension\Controller;

use Psr\Http\Message\ResponseInterface;
use TYPO3\CMS\Extbase\Mvc\Controller\ActionController;

class ConferenceController extends ActionController
{
  public function listAction(): ResponseInterface
  {
    $conferences = $this->conferenceRepository->findAll();

    // Link to the detail action on the same plugin/page,
    // using the first conference as an example
    $uri = $this->uriBuilder->uriFor(
      'show',                                  // action name — no 'Action' suffix
      ['conference' => $conferences->getFirst()],
      'Conference',                            // controller name
    );

    $this->view->assign('conferences', $conferences);
    $this->view->assign('detailUri', $uri);
    return $this->htmlResponse();
  }
}

```

`uriFor()` signature:

**Signature of UriBuilder::uriFor()**

```php
uriFor(
    ?string $actionName = null,
    ?array $controllerArguments = null,
    ?string $controllerName = null,
    ?string $extensionName = null,
    ?string $pluginName = null,
): string
```

All parameters are optional. When omitted, the current controller, extension,
and plugin are used. Only pass `$extensionName` and `$pluginName`
when linking to a different plugin than the one handling the current request.

## Linking to a plugin on a different page {#extbase-routing-uri-builder-target-page}

The most common routing mistake: list and detail are on separate pages, but
the list template generates detail links without telling the UriBuilder which
page to target. The result is a link back to the list page instead of the
detail page.

Use `setTargetPageUid()` before calling `uriFor()`. `reset()`
clears all previously set options — call it before each URL generation inside
a loop:

**EXT:my_extension/Classes/Controller/ConferenceController.php**

```php
<?php

namespace MyVendor\MyExtension\Controller;

use Psr\Http\Message\ResponseInterface;
use TYPO3\CMS\Extbase\Mvc\Controller\ActionController;

class ConferenceController extends ActionController
{
  public function listAction(): ResponseInterface
  {
    $conferences = $this->conferenceRepository->findAll();

    foreach ($conferences as $conference) {
      $uri = $this->uriBuilder
        ->reset()
        // UID of the detail page
        ->setTargetPageUid(42)
        ->uriFor('show', ['conference' => $conference], 'Conference');

      // …
    }

    return $this->htmlResponse();
  }
}

```

The detail page UID is typically stored in TypoScript settings (or site set
settings) so it does not need to be hardcoded:

**EXT:my_extension/Classes/Controller/ConferenceController.php**

```php
$detailPageUid = (int)($this->settings['detailPageUid'] ?? 0);

$uri = $this->uriBuilder
    ->reset()
    ->setTargetPageUid($detailPageUid)
    ->uriFor('show', ['conference' => $conference], 'Conference');
```

## Absolute URLs {#extbase-routing-uri-builder-absolute}

For use in emails, JSON responses, or redirects, generate an absolute URL:

**EXT:my_extension/Classes/Controller/ConferenceController.php**

```php
$uri = $this->uriBuilder
    ->reset()
    ->setCreateAbsoluteUri(true)
    ->uriFor('show', ['conference' => $conference], 'Conference');
```

## Generating URLs in Fluid templates {#extbase-uri-builder-viewhelper}

`<f:link.action>` and `<f:uri.action>` are the Fluid equivalents of
`uriFor()`. When routing configuration is in place, they produce the
same clean URLs automatically.

**EXT:my_extension/Resources/Private/Templates/Conference/List.fluid.html**

```html
<f:link.action action="show" controller="Conference" arguments="{conference: conference}">
    {conference.title}
</f:link.action>
```

To link to a plugin on a different page, use `pageUid`:

**EXT:my_extension/Resources/Private/Templates/Conference/List.fluid.html**

```html
<f:link.action
    action="show"
    controller="Conference"
    arguments="{conference: conference}"
    pageUid="{settings.detailPageUid}"
>
    {conference.title}
</f:link.action>
```

For a plain URL string without an `<a>` tag, use `<f:uri.action>`
with the same attributes — useful when you need to construct the link yourself:

**EXT:my_extension/Resources/Private/Templates/Conference/List.fluid.html**

```html
<a href="{f:uri.action(action: 'show', controller: 'Conference', arguments: '{conference: conference}', pageUid: settings.detailPageUid)}"
   title="{conference.title}"
   class="conference-link">{conference.title}</a>
```

> [!NOTE]
> **See also**
>
> -   [f:link.action ViewHelper reference](https://docs.typo3.org/other/typo3/view-helper-reference/main/en-us/Global/Link/Action.html#typo3-fluid-link-action)
> -   [f:uri.action ViewHelper reference](https://docs.typo3.org/other/typo3/view-helper-reference/main/en-us/Global/Uri/Action.html#typo3-fluid-uri-action)

## Why is my URL not clean? {#extbase-routing-uri-builder-checklist}

If a URL comes out as a raw query string with `cHash` instead of the
expected clean URL, work through this list:

-   **No enhancer configured** — the plugin has no entry under
    `routeEnhancers` in
    [`EXT:my_extension/Configuration/Sets/MyExtension/route-enhancers.yaml`](../../FileStructure/Configuration/Sets/Index.md#file-set-route-enhancers-yaml)
    or `config/sites/<site-identifier>/config.yaml`.
-   **Wrong page** — `setTargetPageUid()` (or `pageUid` in Fluid)
    is missing or points to the wrong page. The enhancer's `limitToPages`
    must include the target page UID or match the page via an expression.
-   **No matching route variant** — the controller/action combination passed
    to `uriFor()` does not match any `_controller` entry in the
    `routes` list in
    [`EXT:my_extension/Configuration/Sets/MyExtension/route-enhancers.yaml`](../../FileStructure/Configuration/Sets/Index.md#file-set-route-enhancers-yaml).
-   **Missing aspect** — a placeholder has a `d+` requirement but no
    [StaticRangeMapper](https://docs.typo3.org/permalink/t3coreapi:extbase-routing-aspects-static-range@main) or
    [StaticValueMapper](https://docs.typo3.org/permalink/t3coreapi:extbase-routing-aspects-static-value@main) aspect,
    so TYPO3 cannot treat the parameter as static and appends `cHash`.
-   **Stale cache** — after changing the site configuration, clear all caches
    via **Admin Tools > Maintenance**.

With URLs generating correctly, see [Routing examples and common mistakes](https://docs.typo3.org/permalink/t3coreapi:extbase-routing-examples@main) for
complete worked examples covering the most common plugin configurations.
