simple_link_preview 2.1.0
simple_link_preview: ^2.1.0 copied to clipboard
Lightweight link previews for HTML metadata, direct images, and other web content types.
Simple Link Preview #
Fetch lightweight metadata for HTTP and HTTPS links. HTML responses are parsed
only from the document <head>, while images and other content types are
returned without downloading their full body.
Installation #
dependencies:
simple_link_preview: ^2.1.0
Usage #
import 'dart:convert';
import 'package:simple_link_preview/simple_link_preview.dart';
Future<void> main() async {
final preview = await SimpleLinkPreview.getPreview(
'https://pub.dev/',
options: const LinkPreviewOptions(
timeout: Duration(seconds: 10),
maxHtmlBytes: 1024 * 1024,
maxRedirects: 5,
),
onError: (error) async {
print('Could not load preview: $error');
return null;
},
);
if (preview == null) {
print('The preview could not be loaded.');
return;
}
if (!preview.hasMetadata) {
print('The resource loaded successfully but has no preview metadata.');
return;
}
print(jsonEncode(preview.toJson()));
}
Example HTML result:
{
"url": "https://pub.dev/",
"contentType": "text/html",
"title": "Dart packages",
"image": "https://pub.dev/static/img/pub-dev-icon-cover-image.png",
"icon": "https://pub.dev/favicon.ico",
"description": "The official package repository for Dart and Flutter apps."
}
Result fields #
| Field | Description |
|---|---|
url |
Original URL supplied by the caller. |
contentType |
Normalized MIME type without parameters such as charset. |
title |
Page title extracted from HTML metadata. |
description |
Page description extracted from HTML metadata. |
image |
Metadata image, or the requested resource URL for image/*. |
icon |
Page icon declared in the HTML <head>. |
hasMetadata |
Whether at least one non-blank title, description, image, or icon is available. |
The result has three distinct states:
null: the preview could not be loaded.- A
LinkPreviewwithhasMetadata == false: the resource loaded successfully, but it has no metadata useful for rendering a preview. - A
LinkPreviewwithhasMetadata == true: at least one display metadata field is available.
All stored fields except url are nullable. hasMetadata is a derived getter;
url, contentType, and blank metadata values do not make it true. Use
toJson() to convert the stored preview fields into a JSON-compatible map.
onError is optional and defaults to null. When provided, it receives a
structured LinkPreviewException and may asynchronously return a fallback
LinkPreview. Without a handler, failures result in null.
final preview = await SimpleLinkPreview.getPreview(
url,
onError: (error) async {
print(error.code);
print(error.statusCode);
print(error.message);
return null;
},
);
Verified failures use these stable error codes:
| Error code | Meaning |
|---|---|
invalidUrl |
URL is not an absolute HTTP or HTTPS URL. |
invalidOptions |
A configurable limit is invalid. |
httpStatus |
validateStatus rejected the response; statusCode is available. |
timeout |
Sending or reading exceeded the configured timeout. |
network |
HTTP client could not complete the request. |
parsing |
Response metadata could not be parsed or resolved. |
unexpected |
An otherwise unclassified failure occurred. |
LinkPreviewOptions exposes timeout, maxHtmlBytes, maxRedirects, and a
validateStatus callback modeled after Dio. By default, only statuses from 200
through 299 are accepted. A response rejected by this callback is reported as
httpStatus.
To parse metadata from selected error pages while preserving the default successful range:
final preview = await SimpleLinkPreview.getPreview(
url,
options: LinkPreviewOptions(
validateStatus: (statusCode) =>
statusCode >= 200 && statusCode < 300 || statusCode == 404,
),
);
Content-type behavior #
image/*: returns the final URL after redirects inimage.text/htmlandapplication/xhtml+xml: parses metadata from<head>.- Missing
Content-Type: sniffs at most the first 1 KB for common HTML roots, then parses the bounded HTML head only when HTML is detected. - Other successful types, such as PDF, video, audio, or JSON: returns the
normalized
contentTypeand leaves unavailable metadata fields asnull. - Invalid URLs, invalid options, timeouts, network failures, redirect failures,
and statuses rejected by
validateStatusare reported throughonError. They returnnullwhen no handler or fallback preview is provided.
HTML metadata uses the following priority. Open Graph values use the standard
property attribute first and accept name as a compatibility fallback:
- Title: Open Graph, Twitter Card, then
<title>. - Description: Open Graph, Twitter Card, then standard description metadata.
- Image: Open Graph, Twitter Card, then
itemprop="image". - Icon: Apple touch icon, standard link icon, then Microsoft tile image.
Empty or invalid HTTP(S) image and icon candidates are skipped. Relative
metadata URLs honor the first valid HTTP(S) <base href> and otherwise resolve
against the final response URL.
The package does not inspect <img> elements in the document body and does not
make a separate favicon request.
Network limits #
- Uses one logical streamed GET request; the HTTP client may follow redirects.
- Reads HTML until
</head>or a maximum of 1 MB. The 1 MB value is only an upper bound; reading stops earlier as soon as the closing head tag is found. - Uses one 10-second end-to-end deadline by default and follows at most five redirects.
- Accepts only absolute HTTP and HTTPS URLs.
On web platforms, cross-origin requests remain subject to the target server's CORS policy.
Features and bugs #
Please file feature requests and bugs at the issue tracker.