Skip to content

Commit 8fb34f6

Browse files
committed
✨feat: add Expand-ShortURL function to expand shortened URLs
1 parent 9b1d53e commit 8fb34f6

File tree

1 file changed

+81
-0
lines changed

1 file changed

+81
-0
lines changed

General/Expand-ShortUrl.ps1

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
function Expand-ShortURL {
2+
<#
3+
.SYNOPSIS
4+
Expand shortened URLs to reveal their destination.
5+
6+
.DESCRIPTION
7+
Expands shortened URLs by revealing the Location header of the destination address. This function handles
8+
single-level redirects only and does not automatically resolve nested shorteners.
9+
10+
.PARAMETER URL
11+
The shortened URL to expand. Can be provided as a string or URI object.
12+
13+
.OUTPUTS
14+
System.String
15+
Returns the expanded URL as a string, or the original URL if no redirect is found.
16+
17+
.EXAMPLE
18+
Expand-ShortURL -URL "https://bit.ly/3example"
19+
20+
Expands a bit.ly shortened URL to its full destination.
21+
22+
.EXAMPLE
23+
"https://tinyurl.com/example", "https://bit.ly/another" | Expand-ShortURL
24+
25+
Demonstrates pipeline usage to expand multiple URLs.
26+
27+
.NOTES
28+
Inspired by @md's concept at https://xkln.net/blog/expanding-shortened-urls-with-powershell/
29+
30+
This function uses HTTP HEAD requests with zero redirects to capture the Location header.
31+
Some URL shorteners may require different approaches or may block automated requests.
32+
33+
.LINK
34+
https://xkln.net/blog/expanding-shortened-urls-with-powershell/
35+
#>
36+
[CmdletBinding()]
37+
[Alias('ExpandUrl')]
38+
param (
39+
# The shortened URL to expand
40+
[Parameter(Mandatory, Position = 0, ValueFromPipeline, ValueFromPipelineByPropertyName)]
41+
[ValidateNotNullOrEmpty()]
42+
[Alias('URI', 'Link')]
43+
[string]$URL
44+
)
45+
46+
process {
47+
Write-Verbose "Attempting to expand URL: $URL"
48+
49+
try {
50+
# Ensure URL has a scheme
51+
if ($URL -notmatch '^https?://' -and $URL -notmatch '^http?://') {
52+
$URL = "https://$URL"
53+
Write-Verbose "Added HTTPS scheme to URL: $URL"
54+
}
55+
56+
# Try to get redirect location using HEAD request with zero redirects
57+
$Response = Invoke-WebRequest -Uri $URL -Method Head -MaximumRedirection 0 -ErrorAction Stop
58+
59+
# If we get here, there was no redirect
60+
Write-Verbose "No redirect found for: $URL"
61+
return $URL
62+
63+
} catch [System.Net.WebException] {
64+
# Check if this is a redirect response (3xx status codes)
65+
if ($_.Exception.Response -and $_.Exception.Response.StatusCode -match '^3\d\d$') {
66+
$ExpandedUrl = $_.Exception.Response.Headers.Location
67+
if ($ExpandedUrl) {
68+
Write-Verbose "Expanded URL: $URL -> $ExpandedUrl"
69+
return $ExpandedUrl.ToString()
70+
}
71+
}
72+
73+
Write-Warning "Failed to expand URL '$URL': $($_.Exception.Message)"
74+
return $URL
75+
76+
} catch {
77+
Write-Warning "Unexpected error expanding URL '$URL': $($_.Exception.Message)"
78+
return $URL
79+
}
80+
}
81+
}

0 commit comments

Comments
 (0)