CSV Import¶
Short URL supports bulk-creating short URLs from a CSV file, via an admin form or a Drush command.
CSV format¶
The CSV file uses positional columns in this order:
| Column | Required | Default | Description |
|---|---|---|---|
slug |
Custom mode only | — | The vanity slug. Ignored for base36 and auto-increment modes. |
destination |
Yes | — | External URL or internal path |
slug_mode |
No | base36 |
custom, base36, or auto_increment |
label |
No | — | Optional human-readable label |
langcode |
No | Site default | Language code (e.g. en, fr) |
redirect_status |
No | Config default | 301, 302, or 307 |
domain |
No | — | Domain machine name (requires domain_shorturl) |
Example¶
slug,destination,slug_mode,label,langcode,redirect_status,domain
promo,https://example.com/spring-sale,custom,Spring Sale,en,301,
,https://example.com/page1,base36,,,,
,https://example.com/page2,auto_increment,,,,
blog,https://example.com/blog,custom,Blog,en,301,example_com
Format auto-detection¶
When uploading a CSV file, the importer automatically detects known formats by matching the header row. Currently supported:
| Format | Expected headers | Column mapping |
|---|---|---|
| YOURLS | source, target, hits |
source → slug, target → destination |
Detection is BOM-safe (UTF-8 BOM is stripped) and tolerates extra trailing columns beyond the expected headers.
When a format is detected, a format defaults step appears
where you can configure default values for columns not present
in the source file (e.g. language, redirect status). Some values
may be enforced by the format — for example, YOURLS enforces
slug_mode=custom since all YOURLS URLs have custom slugs.
Other modules can register additional formats via
hook_shorturl_csv_formats_alter(). See ShortUrlCsvFormatInterface
for the format contract.
Updating existing short URLs¶
When importing slugs that already exist in the database, the importer can update the existing short URL instead of skipping the row. This is controlled by:
- Admin form: the "Update existing short URLs" checkbox (enabled by default)
- Drush: the
--update-existingflag (enabled by default, disable with--no-update-existing)
In the preview step, the Action column shows whether each row will Create a new short URL or Update an existing one. The summary and import button also display separate counts.
Admin form¶
Navigate to Content > Short URLs and click the Import short
URLs action link, or go directly to
/admin/content/short-urls/import.
Step 1: Upload¶
- Select a CSV file (
.csvor.txt, max 10 MB) - Choose the delimiter (comma, semicolon, or tab)
- Check "Skip first row" if the file has a header row
- Check "Update existing short URLs" to update rows with existing slugs instead of skipping them
- Click Preview
Step 1.5: Format defaults (auto-detected formats only)¶
When a known format is detected (e.g. YOURLS), this step appears to let you configure defaults for unmapped columns:
- Slug mode — enforced by YOURLS (custom), editable for other formats
- Language — defaults to the site default language
- Redirect status — defaults to 301 (Permanent)
Click Preview to continue or Back to change the file.
Step 2: Preview and confirm¶
The form displays:
- A summary of valid and invalid rows with create/update counts
- A table listing each valid row with its columns and action
- Error details for invalid rows (with line numbers)
Rows with errors are skipped during import. Click Import to create or update nodes for all valid rows via Batch API.
Permission required: Import short URLs from CSV
Drush command¶
drush shorturl:import /path/to/urls.csv
Known CSV formats (e.g. YOURLS) are automatically detected from the header row. When a format is detected, columns are mapped automatically and the header is skipped.
Options¶
| Option | Default | Description |
|---|---|---|
--delimiter |
, |
CSV delimiter character |
--skip-header |
No | Skip the first row |
--update-existing |
Yes | Update existing slugs instead of skipping |
--dry-run |
No | Validate only, do not create or update nodes |
Examples¶
# Basic import
drush shorturl:import urls.csv --skip-header
# Import a YOURLS export (auto-detected)
drush shorturl:import yourls_export.csv
# Semicolon-delimited file
drush shorturl:import urls.csv --delimiter=";" --skip-header
# Skip existing slugs instead of updating
drush shorturl:import urls.csv --no-update-existing
# Validate without importing
drush shorturl:import urls.csv --skip-header --dry-run
The command displays validation results, asks for confirmation when errors are found, and shows a progress log during import.
Validation rules¶
Each row is validated before import:
- Destination is required and must be a valid URL (external)
or internal path (starting with
/) - Slug is required for custom mode and must contain only
a-z,0-9,_, and- - Slug uniqueness is checked against other rows in the same CSV. Existing slugs in the database are either marked for update or rejected, depending on the update-existing setting
- Slug mode must be
custom,base36, orauto_increment - Permission — the importing user must have the permission for the slug mode used in each row
- Language must be an installed language
- Redirect status must be 301, 302, or 307
- Domain (when using domain_shorturl) must be a valid domain machine name; slug uniqueness is scoped per domain
Domain support¶
When the Domain Short URL
module is installed, the domain column is supported. Each row
can specify a domain machine name to scope the short URL to a
specific domain. Slug uniqueness is then checked per domain,
allowing the same slug on different domains.