Skip to content

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-existing flag (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 (.csv or .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, or auto_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.