UrlPreviewParser 1.1.0
dotnet add package UrlPreviewParser --version 1.1.0
NuGet\Install-Package UrlPreviewParser -Version 1.1.0
<PackageReference Include="UrlPreviewParser" Version="1.1.0" />
<PackageVersion Include="UrlPreviewParser" Version="1.1.0" />
<PackageReference Include="UrlPreviewParser" />
paket add UrlPreviewParser --version 1.1.0
#r "nuget: UrlPreviewParser, 1.1.0"
#:package UrlPreviewParser@1.1.0
#addin nuget:?package=UrlPreviewParser&version=1.1.0
#tool nuget:?package=UrlPreviewParser&version=1.1.0
UrlPreviewParser
A .NET library for extracting link preview metadata (OpenGraph, Twitter Card, oEmbed) from URLs.
Installation
.NET CLI
dotnet add package UrlPreviewParser
Package Manager
Install-Package UrlPreviewParser
PackageReference
<PackageReference Include="UrlPreviewParser" Version="1.1.0" />
Quick Start
using UrlPreviewParser;
using var client = new UrlPreviewClient();
var result = await client.GetPreviewAsync("https://example.com");
// OpenGraph
Console.WriteLine(result.OpenGraph.Title);
Console.WriteLine(result.OpenGraph.Description);
Console.WriteLine(result.OpenGraph.Image);
// Twitter Card
Console.WriteLine(result.TwitterCard.Title);
Console.WriteLine(result.TwitterCard.Image);
// Basic page title
Console.WriteLine(result.Tags.Title);
Accessing the Data
OpenGraph (result.OpenGraph)
og:* tags are read from both the property and the name attribute; when a key appears more than once
the first occurrence wins (e.g. the first og:image).
OpenGraphData extends Dictionary<string, string>. Any og:* property is accessible by key
(e.g., result.OpenGraph["og:title"]). Convenience properties cover the most common fields:
| Property | Key |
|---|---|
Title |
og:title |
Description |
og:description |
Image |
og:image |
Url |
og:url |
Type |
og:type |
SiteName |
og:site_name |
Twitter Card (result.TwitterCard)
twitter:* tags are read from both the name and the property attribute (first occurrence wins).
TwitterCardData extends Dictionary<string, string>. Any twitter:* property is accessible
by key (e.g., result.TwitterCard["twitter:label1"]). Convenience properties:
| Property | Key | Notes |
|---|---|---|
Card |
twitter:card |
e.g. summary, summary_large_image |
Title |
twitter:title |
|
Description |
twitter:description |
|
Image |
twitter:image |
Falls back to twitter:image:src |
Url |
twitter:url |
|
Site |
twitter:site |
@username of the website |
Creator |
twitter:creator |
@username of the content creator |
oEmbed (result.Oembed)
Discovered oEmbed endpoint URLs and the raw response body:
| Property | Type | Description |
|---|---|---|
Json |
string? |
URL of the JSON oEmbed endpoint |
Xml |
string? |
URL of the XML oEmbed endpoint |
Formats |
List<string> |
Discovered format names (e.g. "json", "xml") |
Body |
string? |
Raw response body from the oEmbed endpoint |
Error |
string? |
Error message if the endpoint fetch failed |
Tags (result.Tags)
| Property | Type | Description |
|---|---|---|
Title |
string? |
Content of the first HTML <title> element |
Images |
List<string> |
Image URLs found on the page |
Description |
string? |
<meta name="description"> |
Canonical |
string? |
<link rel="canonical"> |
Favicon |
string? |
First rel="icon" (incl. shortcut icon), else apple-touch-icon, mask-icon, … |
Language |
string? |
lang attribute of <html> |
Charset |
string? |
<meta charset> or <meta http-equiv="Content-Type"> |
Viewport |
string? |
<meta name="viewport"> |
Robots |
string? |
<meta name="robots"> |
ThemeColor |
string? |
<meta name="theme-color"> |
Generator |
string? |
<meta name="generator"> |
Raw head elements (result.Head)
result.Head is a List<Dictionary<string, string?>> containing the raw attributes of every
child element of <head>. Useful when you need access to tags not covered by the typed properties.
Values in Head are never modified (relative URLs stay relative).
URLs
result.Url is the requested URL; result.FinalUrl is the URL actually parsed after redirects.
By default relative URLs in URL-valued properties (og:image, og:url, og:video, og:audio and their
:url/:secure_url variants, twitter:image, twitter:image:src, twitter:player, twitter:url,
Tags.Canonical, Tags.Favicon, oEmbed endpoints) are resolved to absolute URLs against <base href>
or FinalUrl. Absolute values (including data: URIs) and non-URL values such as og:image:width are
left untouched.
Options
var options = new UrlPreviewOptions
{
Timeout = TimeSpan.FromSeconds(10), // default 15 s; null = only HttpClient.Timeout
MaxContentLength = 2 * 1024 * 1024, // default 5 MB; the rest of the body is ignored
FetchOembed = false, // default true
ResolveRelativeUrls = true, // default true
};
using var client = new UrlPreviewClient(httpClient, options);
When the timeout elapses GetPreviewAsync throws a TimeoutException; non-success status codes
throw an HttpRequestException (with StatusCode set on .NET 5+).
The body is decoded with the charset from the Content-Type header, a byte order mark, or a
<meta charset> in the first 1024 bytes, falling back to UTF-8. To support legacy code pages such as
windows-1252 on .NET, register the provider once at startup:
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
Using Your Own HttpClient
When using dependency injection, pass your HttpClient directly. The caller is responsible for
its lifetime; UrlPreviewClient will not dispose it.
// ASP.NET Core — register via IHttpClientFactory
builder.Services.AddHttpClient<MyService>();
// Then inject and use
public class MyService(IHttpClientFactory factory)
{
public async Task<UrlPreviewResult> GetPreviewAsync(string url, CancellationToken ct)
{
var httpClient = factory.CreateClient();
using var client = new UrlPreviewClient(httpClient);
return await client.GetPreviewAsync(url, ct);
}
}
Offline Parsing
ParseAsync parses metadata from an HTML string without making any HTTP requests. The oEmbed
endpoint is discovered but not fetched.
using var client = new UrlPreviewClient();
var result = await client.ParseAsync("https://example.com", htmlString);
License
MIT — see LICENSE for details.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
| .NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
| .NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen40 was computed. tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.0
- AngleSharp (>= 1.8.4)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.