CLI tools and backend modules to bulk-import and export TYPO3 redirects from/to CSV.
Target URLs are automatically resolved to t3://page?uid=X links via TYPO3's routing - no manual page ID lookup needed,
including error check.
- TYPO3 13.4 LTS or 14 LTS
- EXT:redirects
composer require georgringer/redirect-generatorExtension configuration options (Admin → Settings → Extension Configuration):
| Option | Description |
|---|---|
notification_email |
Comma-separated list of addresses for import/export notifications |
notification_level |
0 = errors only · 1 = + warnings · 2 = + info |
allow_empty_import_file |
If true, an empty CSV file silently skips the import instead of throwing an error |
./bin/typo3 redirect:add <source> <target> [--status-code=307] [--dry-run]The target must be a full URL of a page on this TYPO3 instance. It is resolved to the corresponding page ID automatically.
./bin/typo3 redirect:add /old-path https://example.com/new-page --status-code=301./bin/typo3 redirect:import <file.csv> [--dry-run] [--external-domains=domain1,domain2] [--delete-file]CSV format — semicolon-delimited, first row must be the header:
source;target;status_code;external
/old-page;https://example.com/new-page;301;0
/old-section/article;https://example.com/news/article;307;0
/external-link;https://other-domain.com/page;301;1| Column | Required | Description |
|---|---|---|
source |
yes | Source path (e.g. /old-page) |
target |
yes | Full target URL. Internal pages are resolved to t3://page?uid=X. Set external=1 to skip resolution. |
status_code |
no | HTTP status code. Falls back to 307 if omitted or invalid. |
external |
no | 1 = store target URL as-is without page lookup |
Set a target value of x to skip a row.
Options:
| Option | Description |
|---|---|
--dry-run |
Simulate import without writing to the database |
--delimiter |
CSV delimiter: ; (default), , or tab |
--external-domains |
Comma-separated list of domains always treated as external |
--delete-file |
Delete the CSV file after import |
This command is schedulable (TYPO3 Scheduler → Execute console commands).
./bin/typo3 redirect:export <output.csv> [--transform-target-url]--transform-target-url resolves stored t3://page?uid=X links back to readable URLs.
This command is schedulable.
The companion extension georgringer/redirect-generator-ui adds a full backend module under Link Management with import and export forms — no CLI access required.
More information: ringer.it/extensions/redirect-generator-ui
composer require georgringer/redirect-generator-ui
![]() Module in the backend navigation |
![]() Export — filter by type, resolve target URLs |
![]() Import — live result with per-row feedback |
![]() Import — conflicts and errors shown inline |
Features:
- Paste CSV directly into a textarea — no file upload or server access needed
- Choose delimiter (
;,tab) and default status code per import run - Dry-run mode to preview results before writing
- Per-row result feedback: imported, skipped, conflicting duplicates, errors
- Export with optional filter by redirect type or creation type
- Resolve stored
t3://pagelinks to readable URLs on export
Two events are dispatched from RedirectRepository::addRedirect() (not fired during dry runs):
Fired just before the database insert. Listeners may modify source URL, target URL, or the Configuration object.
use GeorgRinger\RedirectGenerator\Event\BeforeRedirectAddedEvent;
class MyListener
{
public function __invoke(BeforeRedirectAddedEvent $event): void
{
// Force all new redirects to 301
$event->setConfiguration(
new Configuration(targetStatusCode: 301)
);
}
}Fired after the insert. Provides sourceUrl, targetUrl, configuration, and the new uid.
use GeorgRinger\RedirectGenerator\Event\AfterRedirectAddedEvent;
class MyListener
{
public function __invoke(AfterRedirectAddedEvent $event): void
{
// e.g. flush a custom cache, send a webhook, ...
}
}Register listeners in your extension's Services.yaml:



