To migrate from TinyURL, first sort your links into two piles: links on a domain you own, and links on tinyurl.com. The first pile moves cleanly, because you change one DNS record and the old URLs keep working. The second pile cannot be redirected by you at all, because TinyURL owns the domain. You can copy the destinations into Elido, but every place a tinyurl.com/xxxx link was published has to be updated by hand.
The second thing to know before you start: right now the dependable way to move is a file. Export through TinyURL's documented GET /urls/available call, reduce the result to destination, slug, title, and load it with Elido's bulk import. Elido also ships a one-click TinyURL importer, but it calls an endpoint that isn't in TinyURL's published API, so we treat it as unverified until a planned fix lands. This guide covers both routes and the full journey: from export to analytics, with the cutover and rollback in between. TinyURL facts are from its own blog and OpenAPI spec, accessed 2026-10-01 and 2026-10-02.
For a feature-by-feature verdict on whether to switch at all, read Elido vs TinyURL or the wider TinyURL alternatives roundup.
Which TinyURL Links Can Move
Ownership of the hostname decides everything. A short link is two things: a hostname and a code. You can carry a code anywhere, but you can only make a link keep working if you control the hostname.
| Link type | Who controls the redirect | What you can do |
|---|---|---|
tinyurl.com/xxxx, created without an account | TinyURL | Nothing to the old link. Re-create the destination in Elido and replace the old link wherever it was published |
tinyurl.com/your-alias, created in an account | TinyURL | Edit the destination inside TinyURL on a paid plan, or import the alias to Elido under a new hostname and update every placement |
go.yourbrand.com/xxxx (custom domain) | You | Point the hostname at Elido and import the aliases. Old URLs keep working |
The honest version for the first two rows: once you stop paying TinyURL, those links keep resolving as long as TinyURL keeps them, and you have no way to see clicks, change them, or redirect them. Some teams leave them alone on purpose. I think that's the right call for old, low-traffic links.
Step 1: Export Your TinyURL Links
TinyURL gives you one documented way to list your links: the API. Its OpenAPI spec (accessed 2026-10-02) defines listing as GET /urls/{type}, where type is available or archived, with optional from and to datetimes and a search filter that takes an alias: or tag: prefix. The call needs a bearer token. TinyURL's own article on listing links describes the same endpoint and says the type is the only mandatory input.
What the spec doesn't give you matters just as much. It defines no page or per_page parameters and no rate limits. So for a large account, narrow each request with from/to windows (a month at a time, say) and write every response to disk before doing anything else:
# One window at a time; inspect the first response by hand before scripting further
curl -s -H "Authorization: Bearer $TINYURL_TOKEN" \
"https://api.tinyurl.com/urls/available?from=2025-01-01T00:00:00Z&to=2025-02-01T00:00:00Z" \
> tinyurl-2025-01.json
We haven't verified the live response shape (the spec leaves unclear whether it carries a list or a single object), so open one file and look before you write a parser. Run the same call against /urls/archived if you want archived links too.
Three limits shape the rest of the plan:
- No account, no list. TinyURL states that links created without signing in cannot be managed or deleted. There's no per-user record, so there's nothing to export.
- The free plan is read-only. Per TinyURL's free plan page, editing and deleting links, click analytics, custom domains and bulk creation all sit behind paid plans.
- Analytics aren't in the list. Click history is on you. Screenshot it or report it out of TinyURL before you cancel. We couldn't find a documented CSV export button in TinyURL's help centre, so this guide doesn't promise one.
Step 2: Map TinyURL Data to a File Elido Accepts
Whatever you pulled out of TinyURL, reduce it to the same three fields:
- TinyURL long URL becomes
destination(the link's target). - TinyURL alias becomes
slug. Leave it blank for links ontinyurl.comthat you want fresh codes for. - TinyURL title or description becomes
title.
TinyURL calls them aliases, Elido calls them slugs. Same thing: the characters after the host. If your target domain is empty, aliases carry over unchanged.
Elido's links page has a bulk tab and a CSV tab, and both read lines in the form url, slug, title. In the CSV tab, the first line is dropped when it doesn't contain an http(s):// URL, so a header row is safe. Lines starting with # are ignored in the paste box. Custom slugs are letters, numbers and hyphens, so check aliases with any other characters before you upload; rows that fail are listed with a reason.
destination,slug,title
https://acme.com/spring-sale,spring-sale,Spring Sale
https://acme.com/pricing,,Pricing page
If you used TinyURL tags, keep them. They won't fit the three-column CSV, but the API route below takes them.
Step 3: Import Into Elido
There are two routes in. The file route works today. The built-in importer exists but is unverified.
The dependable route: CSV, bulk paste or the bulk API
The dashboard bulk and CSV tabs process up to 100 links per batch, so split a larger file into chunks. The bulk import help page walks through the form, and the Google Sheets bulk import walkthrough is handy if you cleaned the export in a spreadsheet.
The workspace API takes the same shape as JSON. POST /v1/workspaces/{workspace_id}/links/bulk accepts a domain_id and up to 100 links, each with destination_url and optional slug, title and tags. Each row is processed on its own, so one bad row doesn't fail the batch, and the response tells you which rows errored. Add a tag such as imported:tinyurl yourself so you can filter the batch later. API and SDKs has the client libraries.
The built-in TinyURL importer, and its known bug
Elido has a one-click TinyURL importer, described on the migrate from TinyURL page. You paste a TinyURL API token, pick the Elido domain the links should land on, and choose a conflict strategy. The problem is the first HTTP call. The worker builds this request:
GET https://api.tinyurl.com/aliases?page=1&per_page=100
Authorization: Bearer <token>
and expects {"data": [{alias, url, title, tags}], "meta": {"total", "has_more"}} back. TinyURL's spec has no /aliases path; alias operations live under /alias/{domain}/{alias}, and listing is /urls/{type}. So that pagination contract was never taken from TinyURL. Our unit test serves a hand-written response in the assumed shape and passes, which proves the parser matches our assumption and nothing about TinyURL. We haven't run it against a live account, because that needs a paid TinyURL plan. Don't plan a migration around it yet.
The fix is planned: switch to /urls/available (with /urls/archived behind a flag), page through from/to windows, parse defensively, and test against a real captured response. After that, pagination and the real per-request limit need re-measuring against a live account, since the spec gives neither.
The integrations page in a DEMO workspace with synthetic data. The TinyURL migration is started from here.
What the importer does once it has a page
Everything past the HTTP call doesn't depend on the endpoint question, and this part we can state from the code.
- Start.
POSTwithtoken,target_domain_idand optionalconflict_strategy. The handler rejects an empty token, a missing domain and any strategy outsidesuffix,skip,fail, then answers202with the job and runs the worker in the background, detached from the request. - Per link. A row without a URL or without an alias counts as failed with a reason. Otherwise the alias becomes the slug, destination and title are copied (title truncated to 200 characters), and tags are copied with
imported:tinyurlappended. - Progress. Counters flush to the job row every 50 links. At most 1,000 error rows are logged per job.
- Auth and rate errors. A 401 or 403 fails the job with a "check the bearer token" message, and a 429 fails it as rate-limited. There's no retry or backoff: the job stops.
The token goes from the request body to the background job and nowhere else. The job row doesn't record it, and nothing is encrypted at rest because nothing is stored. The request body is read with a 4 KB limit. The code doesn't validate the key or check the plan before starting, so a bad one shows up as a failed job after the first request, not as a form error. Earlier versions of our docs described a preflight check against a domains endpoint; that step doesn't exist in the code, and TinyURL's spec has no such path either.
Conflict rules and caps
Before each insert the worker does one indexed lookup for the domain and slug pair:
suffix(default) triesalias-2,alias-3, up toalias-50, and fails the row if all are taken.skipleaves the existing Elido link alone and logs the source row.failfails the job at the first conflict.
Every run is capped at 50,000 links and 30 minutes. Two behaviours are worth knowing. When the 50,000 cap is hit, the loop simply stops and the job completes; it doesn't fail, so compare the final counts with your source total. When the 30-minute budget runs out, the job is marked failed with the number imported so far.
The links list in a DEMO workspace. Imported links carry the imported:tinyurl tag, so you can filter a batch for review.
Testing the importer safely
Whenever the endpoint is fixed, or if you try the importer yourself before then, do it small. Create a throwaway workspace, add an empty domain, and run the job with the fail strategy first. An empty domain means no conflicts, so any failure is a parsing or auth problem rather than a collision. Then compare three numbers: the source count in TinyURL, the total the job reports, and the imported plus skipped plus failed counters. Because the worker takes meta.total from the response it expects, a mismatch between total and your real count is the first sign the response shape differs from what the parser assumes. Filter by imported:tinyurl, open ten links at random, and check destination, slug and title against TinyURL.
Starting a fresh Elido workspace for this takes a couple of minutes; create a free account and add your domain first so it's ready when the import finishes.
Step 4: Cut Over Your Custom Domain
If you run a branded hostname on TinyURL, you're in the easy case. TinyURL's branded domain setup is a CNAME or similar DNS change on a domain you already own, so the same lever works in reverse. Note that the importer doesn't create the domain for you or read a TinyURL domain field. A branded hostname is its own step.
Order matters, because DNS is the last step and the only one visitors feel:
- Lower the record's TTL a day ahead, so the switch lands fast.
- Add the hostname to Elido under Domains and let it verify. The add a domain guide has the exact records, and DNS verification troubleshooting covers the typos behind most stuck "Pending" states.
- Import the aliases onto that hostname while visitors still reach TinyURL.
- Spot-check the imported slugs against the live hostname's old behaviour.
- Change the DNS record. From that moment the hostname resolves to Elido and every old URL on it follows.
Keep the hostname DNS-only, with no CDN proxy in front, because certificate issuance can fail behind one. The wider setup is in custom domains for short links and on the custom domains feature page.
Step 5: Keep Your 301 Redirects Intact
On your own domain the URL doesn't change, so there's nothing to bridge: the same path now answers from Elido. What you protect is the redirect semantics. Redirect status codes are defined in RFC 9110; a permanent redirect tells browsers and search engines the target is stable, and switching long-lived links to temporary changes how they're cached and credited. Read 301 vs 302 redirects for the SEO and caching side.
For tinyurl.com links there's no 301 you can add, because the redirect is TinyURL's. The best you can do is make sure the destination behind the old link stays alive, and replace the link wherever you can reach it. The Bitly migration playbook shows how a 301 bridge works when you do own the old hostname.
Step 6: Verify the Migration
Migration is done when every placement of a link points at something you control. Use this list in order.
- Freeze new links in TinyURL. Create anything new in Elido from now on.
- Archive the TinyURL export files and any reports, with the date.
- Filter the imported batch in Elido by the
imported:tinyurltag. - Compare counts: imported plus skipped plus failed should equal your source row count.
- Fix the failures. Every failed row comes with a reason, usually an invalid URL or a bad slug character.
- Test the top links. Take your 50 most important links and request each one:
curl -s -o /dev/null -w "%{http_code} %{redirect_url}\n" https://go.yourbrand.com/spring-sale
- Compare destination to source for those 50. Match the final URL, including UTM parameters.
- Re-test after DNS from a network that didn't cache the old record.
- Update
tinyurl.complacements. Search email archives, social bios, ad platforms and print fortinyurl.com, and replace what you can.
For the surfaces you can't reach, accept the loss. Old printed QR codes and forgotten posts will keep pointing at TinyURL, and that's true of every shortener migration. The Bitly migration playbook has a stricter verification pass if you want one.
Step 7: Plan Your Rollback
Keep TinyURL for a month if you can, and watch for stragglers before cancelling a paid plan. While TinyURL still serves your branded hostname's links, rollback is one DNS change back to the old record, and the low TTL makes it quick.
Inside Elido, the imported:tinyurl tag is the handle for undoing a batch: filter, then bulk-edit or delete. If an importer run dies mid-way (a deploy or crash stops it, and a sweep every five minutes flips jobs with no progress for 30 minutes to failed), there's no saved cursor, so you restart the job. Re-running is safe under suffix or skip, but suffix will create -2 copies of links the first run already wrote, so prefer skip for a re-run.
Step 8: Set Analytics Expectations
Click history doesn't come across by either route. The importer reads link fields only, and a CSV has no click column. New clicks count from the moment a link is live in Elido, which for a custom domain means from the DNS change. Expect a short window where some visitors still reach TinyURL from cached records.
Also left behind: QR styling and templates, plus anything created without an account. If you track campaigns, carry your UTM conventions across now; UTM parameters explained is a good refresher.
What You Gain by Moving
You leave with links on a hostname you own, so the next migration, if there is one, is a DNS change instead of a project. You also get analytics that start at cutover and a tag you can query. The pricing page lists the plans, and the two posts linked at the top cover the head-to-head and the wider field.
Related on the blog
Frequently asked questions
Can I redirect my tinyurl.com links to a new short link?
No. You do not own tinyurl.com, so only TinyURL can change where a tinyurl.com/xxxx code points. On a paid plan you can edit the destination inside TinyURL, but you cannot point it at a domain-level redirect of your own. The fix is to replace the old link wherever you published it.
How do I export my links from TinyURL?
Use the TinyURL API with a token from a paid account. TinyURL's OpenAPI spec lists links through GET /urls/available and GET /urls/archived, with optional from, to and search filters. Links created without signing in belong to no account, so there is nothing to list.
Does the Elido TinyURL importer work today?
Treat it as unverified. The worker requests a /aliases path that is not in TinyURL's OpenAPI spec (accessed 2026-10-02), so the dependable route right now is exporting through /urls/available and loading the result with Elido's CSV or bulk import. A fix to the importer is planned.
Do I lose my click history when I leave TinyURL?
Yes, for practical purposes. Elido imports destination, alias, title and tags, not click events. Export any reports you need from TinyURL before you cancel, and expect new clicks in Elido to start counting from cutover.
Can I keep my TinyURL custom domain?
Yes, because you own it. Add the hostname to Elido, import the aliases onto it, then change the DNS record at your registrar. Old links on that domain keep working because the hostname now points at Elido instead of TinyURL.
Can I migrate from a free TinyURL account?
Not automatically. Listing links needs an API token, and TinyURL puts editing, analytics, custom domains and bulk creation behind paid plans. On the free plan you rebuild a list of destinations yourself and bulk-create them in Elido.
Try Elido
Paste a URL, get a working short link
No signup. Link lives for 30 days. Sign up to keep it forever.
No signup needed. Sign up free for 50 links a month.