Some features

Here you’ll find some extra Shlink features, which are not as evident, but you might still want to take advantage of.

This document also tries to clarify why some of these features work the way they do.

Short URL title

Shlink v2.6.0 introduces the ability to optionally set a title for every short URL.

The title can be provided, but it’s also possible to enable title auto-resolution. When that’s enabled, and the title is not provided, Shlink will try to infer the title by calling the long URL and picking the value inside the <title /> tag.

The title can be changed later on. If the long URL is changed, it will also try to auto-resolve the new title, unless the title was originally provided during creation.

Query params forwarding

By default, Shlink automatically forwards to the long URL all query params originally sent to the short URL.

For example, if you have a https://exam.ple/abc123 URL that points to, when users visit https://exam.ple/abc123?foo=bar, they will get redirected to

If for any reason the long URL already had query params, they will be merged with the ones sent to the short URL. In case of conflict, the value sent with the short URL will take precedence over the original URL one.

For example, if https://exam.ple/abc123 points to, when users visit https://exam.ple/abc123?foo=overwritten&another=param, they will get redirected to


Starting with Shlink v2.9.0, this behavior can be overwritten on every individual short URL, allowing to disable the query params forwarding if desired.

Extra path forwarding

Starting with Shlink 2.8.0, Shlink can match short URLs as soon as the visited URL starts with an existing short code.

When this happens, Shlink will append the rest of the path to the long URL before redirection.

For example, if you have a https://exam.ple/abc123 URL that points to, you can make Shlink capture visits to https://exam.ple/abc123/shlinkio and redirect to

When this happens, Shlink will track the visit as usual.

This behavior needs to be actively opted in, as it’s disabled by default.

Multi-segment custom slugs

Shlink 3.2.0 introduced the ability to create short URLs with multi-segment custom slugs.

That means that you can provide multiple parts separated by slashes as the custom slug, ending with something like https://exam.ple/my/custom/campaign.

This feature has some considerations though:

  • When this is enabled, any URL will match a potential short URL. That means any future orphan visit will have either base_url or invalid_short_url types, but never regular_404.
  • Because of previous point, this is considered a breaking change, and therefore, it’s disabled by default, and you have to actively opt in.
  • If Extra path forwarding is also enabled, there’s always a chance of conflict. If you have both https://exam.ple/foo and https://exam.ple/foo/bar, when the second one is visited, it will match the first one, and the /bar part will be forwarded to the long URL.

Short URLs trailing slash

Starting with Shlink 3.3.0, you can make the same short URL work whether it has a trailing slash or not. (This feature has to be explicitly enabled via installation tool or environment variables).

This means that, while the feature is enabled, if you create the short URL https://examp.le/foo and a user ends up visiting https://examp.le/foo/, the visit will be properly captured and the user will be redirected.

In older versions of Shlink or when this is not enabled, visiting a short URL with trailing slash results in a 404.

If you want to support trailing slashes in any route known by Shlink and not only short URLs, you can configure the web server in front of Shlink to strip trailing slashes before calling it:

Short URLs mode

By default, Shlink always matches short URLs in a strict mode, meaning it does a case-sensitive check when trying to determine which short URL has been visited.

This effectively means https://s.test/aaabbb and https://s.test/AAABBB are considered different URLs by Shlink.

Starting with Shlink v3.5.0, you can customize this behavior, and make Shlink consider those two URLs to be the same.

This is achieved via the so called loose short URL mode (the mode can be set via installation tool or environment variables).


Setting loose mode has a couple of considerations:

  • Shlink will no longer generate short codes with uppercase letters. Only lowercase and numbers will be taken into consideration.
  • When providing a custom slug, Shlink will lowercase it, so if there’s a URL with aaabbb and AaaBbb is provided, it will throw an error saying it already exists.
  • On existing Shlink instances, already existing short URLs will not be changed in any way. If “conflicting” URLs already exist, they have to be fixed manually.
  • Loose checks are done only for “public” URLs (short URLs, QR codes and email tracking). REST API endpoints do strict matches no matter what.

QR codes

Shlink comes with built-in support to generate QR codes for any short URL.

Getting a QR code URL is as simple as appending /qr-code to any short URL. So if your short URL is https://exam.ple/abc123, the URL which returns the binary QR code image is https://exam.ple/abc123/qr-code.

The image’s default appearance can be customized via installation tool or env vars, but it can also be customized on the fly via query params:

  • size: It determines the width/height in pixels. Default value is 300 and accepts values from 50 to 1000.
  • margin (since v2.6.0) : The space in pixels between the QR code itself and the border of the image. Default value is 0 and accepts positive numbers.
  • format (since v2.4.0) : Can be png or svg. Default values is png.
  • errorCorrection (since v2.8.0) : Can be L (Low), M (Medium), Q (Quartile) or H (High). Default value is L. Learn more.
  • roundBlockSize (since v2.10.0) : Can be true or false. Tells if the block size should be rounded, making the QR code more readable, but potentially adding some extra margin as a side effect.
  • color (since v4.0.0) : Foreground color in hexadecimal, with 3 or 6 characters. Default value is black if not provided or provided value is not a color.
  • bgColor (since v4.0.0) : Background color in hexadecimal, with 3 or 6 characters. Default value is white if not provided or provided value is not a color.

For example https://exam.ple/abc123/qr-code?size=500&format=svg&margin=20&errorCorrection=Q&roundBlockSize=false.

See the “endpoint” docs for more information.


  • The total size of the image will be determined by the size + the margin times two. So, if the size is 500 and the margin is 20, the resulting image will be 540x540 pixels.
  • The logo cannot be customized via query params, to avoid public QR codes from being unintentionally associated with certain images.

Bot detection

Starting with v2.7.0, Shlink can now detect visits from potential bots or crawlers, based on the visitor’s User-Agent header.

Of course, there’s never a 100% accuracy here, hence the potential.

All the endpoints serving visits will include the potentialBot flag with values true or false, and they also allow excluding potential bots from the result set.

Remove expired links

Sometimes you programmatically create “temporary” links that are meant to be used once or during a short period of time, and then get disabled via maxVisits or validUntil.

After some time, you can end up with a bunch of short URLs consuming space, that are never going to receive new visits.

While Shlink does not provide a mechanism to automatically delete them once expired, starting with Shlink 4.1.0, you can use the short-url:delete-expired command to delete all links that are considered expired by the conditions mentioned above.

It’s up to you to configure this command to be run periodically if desired.

Email tracking

Shlink can track how many times an email has been opened, by taking advantage of its URL tracking capabilities.

You can track emails with any existing short URL, or create a new one pointing to a dummy long URL (the redirect itself is not important for this use case).

Then, by appending /track to the short URL, you will have a new URL (for example, that resolves to a 1px transparent image. Add it to any email you want to track.

The image is effectively invisible, but every time the email is opened and the image is loaded, Shlink will count one visit.

Service healthiness

In some situations you may want to know if your Shlink instance is healthy. Reasons might include monitoring, but also letting orchestrators know if one specific instance can respond to requests.

Shlink exposes a /rest/health endpoint, which does not require authentication, and can be used for this purpose.

You can find more information in the API docs.

Device-specific redirects

Shlink 3.5.0 introduced the possibility to dynamically redirect to different long URLs depending on the device used by the visitor.

Shlink v4.0.0 has moved this into a new dynamic rule-based redirects system.