Repository navigation
Versions and Upgrading
From nuget.org, read on 2026-09-29:
| Version | Published | State | Downloads |
|---|---|---|---|
| 2.0.0 | 2026-09-27 | current | 64 |
| 2.0.0-beta.1 | 2026-09-27 | prerelease, the release rehearsal of 2.0.0 | not shown in the search index |
| 1.0.2 | 2016-06-05 | deprecated (legacy) | 2,396 |
| 1.0.0 | 2016-05-30 | deprecated (legacy) | 2,159 |
1.0.2 still installs: a .NET 10 app restored it on 2026-09-29, with NuGet's NU1701 warning because it ships only a .NET Framework 4.5 build (lib/net45). The CHANGELOG has every change.
- New:
ImageUrl.HasImageExtension,ImageUrl.IsImageUrlAsync(four overloads) andImageUrl.ImageExtensions. The old API gained nothing and lost nothing. -
IsImageUrlis marked obsolete (a warning, CS0618 in C# and FS0044 in F#). Its answers and requests are unchanged. - The package declares FSharp.Core 6.0.7 or later. 1.0.2 needed FSharp.Core 4.4.0.0 without declaring it.
- Targets: net10.0, net462 and netstandard2.0, where 1.0.2 had net45 only. .NET Framework 4.5 to 4.6.1 are no longer supported.
The same inputs went through the published 1.0.2 and the published 2.0.0, on .NET 10, against the local stand-in. There, /avatar answers image/png, /about text/html, /upper IMAGE/PNG, /x-imagefile application/x-imagefile, and /gone and any unknown path a 404:
"image.png"
1.0.2 IsImageUrl True
2.0.0 IsImageUrl True
2.0.0 HasImageExtension True
2.0.0 IsImageUrlAsync False
"x.webp"
1.0.2 IsImageUrl UriFormatException
2.0.0 IsImageUrl UriFormatException
2.0.0 HasImageExtension True
2.0.0 IsImageUrlAsync False
"a"
1.0.2 IsImageUrl UriFormatException
2.0.0 IsImageUrl UriFormatException
2.0.0 HasImageExtension False
2.0.0 IsImageUrlAsync False
"photos/cat.png?w=1"
1.0.2 IsImageUrl UriFormatException
2.0.0 IsImageUrl UriFormatException
2.0.0 HasImageExtension True
2.0.0 IsImageUrlAsync False
"ftp://images.test/a.png"
1.0.2 IsImageUrl True
2.0.0 IsImageUrl True
2.0.0 HasImageExtension False
2.0.0 IsImageUrlAsync False
"http://images.test/avatar"
1.0.2 IsImageUrl True (1 request)
2.0.0 IsImageUrl True (1 request)
2.0.0 HasImageExtension False
2.0.0 IsImageUrlAsync True (1 request)
"http://images.test/a.png?size=1"
1.0.2 IsImageUrl WebException (ProtocolError) (1 request)
2.0.0 IsImageUrl WebException (ProtocolError) (1 request)
2.0.0 HasImageExtension True
2.0.0 IsImageUrlAsync True
"http://images.test/about"
1.0.2 IsImageUrl False (1 request)
2.0.0 IsImageUrl False (1 request)
2.0.0 HasImageExtension False
2.0.0 IsImageUrlAsync False (1 request)
"http://images.test/upper"
1.0.2 IsImageUrl False (1 request)
2.0.0 IsImageUrl False (1 request)
2.0.0 HasImageExtension False
2.0.0 IsImageUrlAsync True (1 request)
"http://images.test/x-imagefile"
1.0.2 IsImageUrl True (1 request)
2.0.0 IsImageUrl True (1 request)
2.0.0 HasImageExtension False
2.0.0 IsImageUrlAsync False (1 request)
"http://images.test/gone"
1.0.2 IsImageUrl WebException (ProtocolError) (1 request)
2.0.0 IsImageUrl WebException (ProtocolError) (1 request)
2.0.0 HasImageExtension False
2.0.0 IsImageUrlAsync False (1 request)
"x.GIF" under tr-TR
1.0.2 IsImageUrl UriFormatException
2.0.0 IsImageUrl UriFormatException
2.0.0 HasImageExtension True
2.0.0 IsImageUrlAsync False
same answer 12 of 12; same request heads 12 of 12
That last line compares 2.0.0's IsImageUrl with 1.0.2 run the same day, request headers included.
These are the behaviours 2.0.0 keeps under the old name, as the rows above and the golden recordings show:
- It decides by the text after the last dot of the whole string, query included, so
a.png?size=1sends a request, andftp://images.test/a.pngis true without one. - It throws for input it cannot decide:
UriFormatExceptionfor relative strings such asaorx.webp, andWebExceptionfor every 4xx and 5xx answer. - It matches the
Content-Typeas a case-sensitive substring:IMAGE/PNGis false andapplication/x-imagefileis true. - It depends on the current culture: under tr-TR,
x.GIFlowercases to a dotlessı, misses the list and throws. - It reads local files for
file:URLs, follows redirects to any host and waits up to 100 seconds (from the README and the recordings; not rerun for this page).
| Where 1.x was used as | Use in 2.0.0 |
|---|---|
| an offline check of a name or URL | url.HasImageExtension() |
| a check that may ask the server |
await url.IsImageUrlAsync(), or with your HttpClient and a token |
| a way to catch exceptions for "not sure" | catch HttpRequestException and TaskCanceledException from IsImageUrlAsync only; everything else is false |
Check the rows above where the answer changes: relative names are false in IsImageUrlAsync (use HasImageExtension for them), IMAGE/PNG becomes true, application/x-imagefile becomes false, and ftp: URLs become false. Code that must keep 1.0.2's exact answers can keep calling IsImageUrl and suppress the warning.
The obsolete warning from C# is on the API reference. From F#, this script:
#r "nuget: IsImageUrlDotNet, 2.0.0"
open IsImageUrlDotNet
printfn "%b" (IsImageUrlDotNetLib.IsImageUrl "image.png")prints true and warns:
fs-obsolete.fsx(4,15): warning FS0044: This construct is deprecated. IsImageUrl keeps 1.0.2's answers, bugs included. Use ImageUrl.HasImageExtension (offline) or ImageUrl.IsImageUrlAsync (http and https only).
A C# project that used 1.0.2 without adding FSharp.Core itself failed on the first call. A .NET 10 app with 1.0.2 and nothing else printed:
FileNotFoundException: Could not load file or assembly 'FSharp.Core, Version=4.4.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'. The system cannot find the file specified.
2.0.0 brings FSharp.Core through its dependency, so an explicit FSharp.Core reference added for 1.x can go, unless something else in the project needs it.
The repository keeps recordings of the published 1.0.2 in tests/Golden/: 117 cases each, with every request each case sent. There is one for .NET 10 on Windows, Linux and macOS, one for .NET Framework 4.8 on Windows, and a Mono 6.8 reference. On 2026-09-29 the capture program in tests/Golden/Capture ran again, once against 1.0.2 and once against 2.0.0, one run after the other. The 2.0.0 run used a copy with only the package version changed. Each result was compared with the recording, answers and requests apart. On Windows:
## net10.0 against 1.0.2.net10.0-windows.json (recorded 2026-09-27, .NET 10.0.12, assembly IsImageUrlDotNet 1.0.2.0)
1.0.2 today: same answer 117 of 117, same requests 117 of 117, both 117 of 117 (1 answers equal once the drive letter is swapped, as the golden test does)
2.0.0 today: same answer 117 of 117, same requests 117 of 117, both 117 of 117 (1 answers equal once the drive letter is swapped, as the golden test does)
2.0.0 against 1.0.2, both today: same answer 117, same requests 117, both 117 of 117
## net48 against 1.0.2.net48-windows.json (recorded 2026-09-27, .NET Framework 4.8.9345.0, assembly IsImageUrlDotNet 1.0.2.0)
1.0.2 today: same answer 117 of 117, same requests 117 of 117, both 117 of 117 (1 answers equal once the drive letter is swapped, as the golden test does)
2.0.0 today: same answer 117 of 117, same requests 117 of 117, both 117 of 117 (1 answers equal once the drive letter is swapped, as the golden test does)
2.0.0 against 1.0.2, both today: same answer 117, same requests 117, both 117 of 117
and on Linux (WSL, Ubuntu 26.04):
## net10.0 against 1.0.2.net10.0-linux.json (recorded 2026-09-27, .NET 10.0.12, assembly IsImageUrlDotNet 1.0.2.0)
1.0.2 today: same answer 117 of 117, same requests 117 of 117, both 117 of 117
2.0.0 today: same answer 117 of 117, same requests 117 of 117, both 117 of 117
2.0.0 against 1.0.2, both today: same answer 117, same requests 117, both 117 of 117
The drive letter case is file:///nonexistent-isimageurl/file, whose message names the current drive. The macOS recording and the Mono reference were not replayed.
This wiki describes IsImageUrlDotNet 2.0.0 and was last updated on 2026-09-29. The library is MIT licensed. Report problems in the issues. On NuGet: IsImageUrlDotNet.
Using it
The releases
Contributing
Elsewhere