URL에서 메타데이터를 추출( opengraph_fetch )하고 아름다운 링크 미리보기( OpengraphPreview 위젯 )를 표시하는 이중 기능을 갖춘 완전한 OpenGraph 통합용 Flutter 패키지입니다. OpenGraph, Twitter Cards, HTML 메타 태그 및 JSON-LD 형식을 지원합니다.
opengraph 패키지는 Flutter 앱에서 OpenGraph 통합을 원활하게 제공하여 URL에서 메타데이터를 추출하고 매력적인 링크 미리보기를 렌더링할 수 있습니다. OpenGraph, Twitter Cards, HTML 메타 태그 및 JSON-LD 형식을 지원하며, 소셜 플랫폼 간 콘텐츠 공유에 적합합니다. 시각적으로 매력적인 미리보기를 위한 OpengraphPreview 위젯과 구조화된 데이터를 효율적으로 가져오는 페처 유틸리티를 포함하고 있습니다. 크로스플랫폼 사용을 위해 설계되어 Android, iOS, macOS, Windows, Linux에서 작동합니다.
사용 사례
소셜 미디어 공유
링크 미리보기 생성
콘텐츠 탐색
URL에서 메타데이터 추출
리치 카드 표시
주요 기능
여러 메타데이터 형식을 지원합니다
내장형 미리보기 위젯
크로스 플랫폼 호환성
효율적인 URL 메타데이터 가져오기
반응성 있고 사용자 정의 가능한 UI
적합한 대상
공유 링크가 있는 앱
채팅 또는 메시징 인터페이스
뉴스 또는 콘텐츠 집약 앱
소셜 네트워킹 기능
웹 콘텐츠 통합
고려 사항
메타데이터 가져오기 위해 네트워크 액세스가 필요합니다
성능을 위해 캐싱이 필요할 수 있습니다
외부 URL 콘텐츠의 유효성에 의존
공개적으로 접근 가능한 웹 페이지로 제한
느린 원격 응답으로 인한 지연 가능성
원본 README
연결된 소스 저장소의 README 원문 스냅샷입니다. 최신 내용은 저장소에서 확인하세요.
Flutter OpenGraph Package
What is OpenGraph?
OpenGraph is a protocol that enables any web page to become a rich object in a social graph. It was originally created by Facebook to enable web pages to have the same functionality as other Facebook objects. Today, OpenGraph is used by most social media platforms, search engines, and messaging apps to create rich previews of shared links.
About This Package
The Flutter OpenGraph package provides a comprehensive solution for working with OpenGraph metadata in your Flutter applications. It offers dual functionality:
OpengraphPreview Widget: A customizable Flutter widget that displays beautiful link previews using OpenGraph data from any URL
opengraph_fetch: A powerful function that extracts OpenGraph metadata from URLs, supporting multiple formats
Key Features
Rich Link Previews: Transform plain URLs into engaging visual previews with title, description, and image
Multiple Metadata Formats: Support for OpenGraph, Twitter Cards, HTML meta tags, JSON-LD (including @graph) and favicon fallback
Rich Structured Data: Every og:image/og:video/og:audio object with width/height/alt, plus article:*/book:* tags
Customizable UI: Text styles, overlay color, image fit, tap callback and an alternative horizontal layout
Caching: Efficient memory caching with TTL expiration, in-flight request deduplication and an optional pluggable persistent store so previews survive app restarts
Robust Fetching: URL normalization (www.example.com just works), controlled redirects with relative images resolved against the final URL, charset detection beyond UTF-8, configurable timeout, headers and CORS proxy
Direct API Access: Use the fetch API directly to get raw metadata for custom implementations
All Platforms: Pure package:http networking — works on Android, iOS, web, Windows, macOS and Linux
List-Friendly: Designed for scrollable lists — lazy fetch on viewport entry, memoized fetches, decode at display size, optional blur
Screenshots
Installation
Add the package to your pubspec.yaml file:
dependencies:opengraph:^1.2.0
Then run:
flutter pub get
Getting Started
The package offers two main components that can be used independently or together:
1. OpengraphPreview Widget
This widget displays a rich preview of any URL, showing the title, description, and image extracted from the OpenGraph metadata.
2. opengraph_fetch Function
This function extracts OpenGraph metadata from a URL and returns it as a structured object, allowing you to use the data in your own custom UI.
Usage
No initialization is required: OpengraphPreview and opengraph_fetch work out of the box, with results cached in memory automatically.
Using the OpengraphPreview Widget
The widget allows you to preview OpenGraph data from a URL with various customization options:
OpengraphPreview(
url: "https://www.youtube.com/watch?v=6g4dkBF5anU",
height: 200, // Optional: Custom height for the preview
borderRadius: 10, // Optional: Rounded corners radius
backgroundColor: Colors.black87, // Optional: Background color
progressColor: Colors.white54, // Optional: Loading indicator color
)
Customization Options
The OpengraphPreview widget supports the following customization options:
Parameter
Type
Description
url
String
The URL to fetch OpenGraph data from (required)
height
double
Height of the preview card (default: 200)
borderRadius
double
Radius for the card corners (default: 10)
backgroundColor
Color
Background color of the card (default: black87)
progressColor
Color
Color of the loading indicator (default: white54)
hideOnError
bool
Render nothing when the fetch fails (default: false)
childError
Widget?
Custom widget shown when the fetch fails, replaces the whole card
childPreview
Widget?
Custom widget shown while loading, instead of the progress indicator
showReloadButton
bool
Show a retry button on error that invalidates the cache (default: false)
refresh
String
Label of the retry button (default: "Refresh")
error
String
Message shown when the fetch fails
fallbackImage
Widget?
Custom widget shown when the page has no og:image, instead of the default image
enableBlur
bool
Blur effect behind the text overlay; disable in long lists for better performance (default: true)
titleStyle
TextStyle?
Merged over the default title style (white, bold)
descriptionStyle
TextStyle?
Merged over the default description style (white)
hostStyle
TextStyle?
Merged over the default host style (white54)
titleMaxLines
int
Maximum lines for the title (default: 1)
descriptionMaxLines
int
Maximum lines for the description (default: 2)
overlayColor
Color
Color of the panel behind the texts (default: 50% black)
imageFit
BoxFit
How the image fits its box (default: fitWidth)
onTap
VoidCallback?
Called when the loaded preview is tapped, e.g. to open the URL
layout
OpenGraphLayout
overlay (image with texts on top, default) or horizontal (side image + texts)
lazyLoad
bool
Defer the fetch until the widget is visible (default: false)
visibilityThreshold
double
Visible fraction that starts a lazy fetch (default: 0.1)
Caching
Fetched URLs are cached in memory, so scrolling through lists does not refetch. You can tune or bypass it:
OpengraphCache.maxEntries = 500; // default: 200OpengraphCache.ttl = constDuration(hours: 1); // default: 24h; null = session-longOpengraphCache.evict("https://a.com"); // drop a single URLOpengraphCache.clear(); // drop everythingOpengraphCache.enabled = false; // disable caching entirely// Per-call freshness override:awaitopengraph_fetch(url, maxAge: Duration.zero); // force a refetch
Network failures are not cached, so transient errors recover on the next attempt.
Persistent cache
Previews can survive app restarts by plugging a storage backend into
OpengraphCache.store. The package ships no storage dependency — implement
the small OpengraphCacheStore interface over whatever your app already
uses. With shared_preferences:
import'dart:convert';
import'package:opengraph/opengraph.dart';
import'package:shared_preferences/shared_preferences.dart';
classPrefsCacheStoreimplementsOpengraphCacheStore{
staticconst _prefix = 'og_cache:';
@overrideFuture<OpengraphCacheEntry?> read(String url) async {
final prefs = awaitSharedPreferences.getInstance();
final raw = prefs.getString('$_prefix$url');
if (raw == null) returnnull;
returnOpengraphCacheEntry.fromJson(jsonDecode(raw));
}
@overrideFuture<void> write(String url, OpengraphCacheEntry entry) async {
final prefs = awaitSharedPreferences.getInstance();
await prefs.setString('$_prefix$url', jsonEncode(entry.toJson()));
}
@overrideFuture<void> delete(String url) async {
final prefs = awaitSharedPreferences.getInstance();
await prefs.remove('$_prefix$url');
}
@overrideFuture<void> clear() async {
final prefs = awaitSharedPreferences.getInstance();
for (final key in prefs.getKeys().where((k) => k.startsWith(_prefix))) {
await prefs.remove(key);
}
}
}
voidmain() {
OpengraphCache.store = PrefsCacheStore();
runApp(constMyApp());
}
Memory stays the source of truth: successful fetches write through to the
store, memory misses are answered from it (validated against the same
TTL/maxAge rules) before hitting the network, and any error thrown by the
store is swallowed — a broken store never breaks fetching. Use
OpengraphCache.clear(memoryOnly: true) to free memory without wiping the
persisted entries.
URLs without a scheme (www.example.com) are normalized to https://
before fetching, redirects are followed manually so relative images resolve
against the destination URL, and non-UTF-8 pages (latin1, windows-1252…)
are decoded from the charset declared in the response.
Flutter Web and CORS
On the web the browser enforces CORS, so most third-party sites refuse a
direct fetch. Route the requests through a proxy with
OpengraphFetch.proxyUrl — either a {url} template or a plain prefix
that gets the encoded URL appended:
Relative images keep resolving against the target site, not the proxy.
Note the browser also sets its own User-Agent, custom headers are
subject to CORS preflight, and the preview images themselves still load
from their original hosts.
Lazy loading in lists
With lazyLoad: true the fetch is deferred until the preview scrolls into
the viewport, so a long list does not fire every request at once:
Results land in the cache (with TTL), in-flight requests are deduplicated,
and requests already started keep running to completion so the cache warms
up even if the user scrolls past.
Rich metadata
OpenGraphEntity exposes the full structured protocol beyond the basic
fields:
final entity = awaitopengraph_fetch("https://example.com/article");
entity!.images; // List<OgImage>: every og:image with width/height/alt/secureUrl
entity.images.first.width;
entity.videos; // List<OgVideo>: og:video objects
entity.audios; // List<OgAudio>: og:audio objects
entity.structuredTags; // article:*, book:*, profile:*, music:*, video:* tags
entity.structuredTags['article:tag']; // e.g. ["flutter", "opengraph"]
entity.faviconUrl; // <link rel="icon"> resolved absolute, if any
When a page has no image in any metadata format, the favicon is used as a
last-resort image, so previews still show something recognizable.
You can directly fetch OpenGraph metadata from any URL and use it in your own custom UI:
// Fetch OpenGraph datafinal openGraphData = awaitopengraph_fetch("https://github.com/baldomerocho/flutter_opengraph");
// Access the structured dataprint(openGraphData?.title); // Title of the pageprint(openGraphData?.description); // Description of the pageprint(openGraphData?.image); // Featured image URLprint(openGraphData?.url); // Canonical URLprint(openGraphData?.siteName); // Site nameprint(openGraphData?.type); // Content type (e.g., "website", "article")print(openGraphData?.locale); // Content locale (e.g., "en_US")
Raw Metadata Access
For advanced use cases, you can also access the raw metadata:
// Fetch raw OpenGraph datafinal rawData = awaitopengraph_fetch_raw("https://datogedon.com");
// Access the raw dataprint(rawData?.title);
print(rawData?.description);
// ... other properties
Supported Metadata Formats
The package can extract metadata from multiple formats:
OpenGraph Protocol: Standard og: meta tags (Facebook, most social platforms)
Twitter Cards: Twitter-specific metadata format
HTML Meta Tags: Standard HTML meta tags for title, description, etc.
JSON-LD: Structured data in JSON-LD format (commonly used for SEO)
The extraction process follows a priority order, with OpenGraph tags taking precedence when available, followed by Twitter Cards, then JSON-LD, and finally standard HTML meta tags.
Complete Example
import'package:flutter/material.dart';
import'package:opengraph/opengraph.dart';
voidmain() {
runApp(constMyApp());
}
classMyAppextendsStatelessWidget{
constMyApp({super.key});
@overrideWidgetbuild(BuildContext context) {
returnMaterialApp(
home: Scaffold(
appBar: AppBar(
title: constText('OpenGraph Preview'),
),
body: Column(
children: [
// Example of using the OpengraphPreview widgetconstPadding(
padding: EdgeInsets.all(8.0),
child: OpengraphPreview(
url: "https://www.youtube.com/watch?v=6g4dkBF5anU",
),
),
// Example of using the opengraph_fetch functionalityFutureBuilder(
future: opengraph_fetch("https://github.com/baldomerocho/flutter_opengraph"),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
returnconstCircularProgressIndicator();
}
if (snapshot.hasError || !snapshot.hasData) {
returnconstText("Error fetching data");
}
final data = snapshot.data!;
returnPadding(
padding: constEdgeInsets.all(8.0),
child: Card(
child: Padding(
padding: constEdgeInsets.all(8.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
Text("Title: ${data.title}", style: Theme.of(context).textTheme.titleMedium),
Text("Description: ${data.description}"),
if (data.image.isNotEmpty)
Image.network(data.image, height: 100),
],
),
),
),
);
},
),
],
),
),
);
}
}
## AdvancedUsage
### CombiningBothFeaturesYou can use both the widget and fetch functionality together in your app. For example, you might want to display a preview widget but also use the metadata for other purposes:
```dart
FutureBuilder(
future: opengraph_fetch("https://flutter.dev"),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
returnconstCircularProgressIndicator();
}
// Display the preview widgetreturnColumn(
children: [
// Use the widget for visual previewconstOpengraphPreview(url: "https://flutter.dev"),
// Also use the fetched data for other purposesif (snapshot.hasData)
Text("This content is from: ${snapshot.data!.siteName}"),
],
);
},
)
Error Handling
The package includes built-in error handling to ensure your app remains stable even when URLs are invalid or content cannot be fetched:
try {
final data = awaitopengraph_fetch("https://invalid-url.example");
// Handle success case
} catch (e) {
// Handle error caseprint("Error fetching OpenGraph data: $e");
}
Best Practices
Performance Optimization
Configure Cache Size: Set an appropriate OpengraphCache.maxEntries value based on your app's memory constraints
Long Lists: In scrollable lists with many previews set enableBlur: false — BackdropFilter is expensive per item
Prefetching: Consider prefetching OpenGraph data (opengraph_fetch(url)) for important links — results land in the cache and the widget picks them up instantly
Legacy API
OpenGraphRequest / OpenGraphConfiguration (the pre-1.0 singleton API) are deprecated as of 1.3.0 and will be removed in 2.0.0. They keep working — and now send the configured request headers and decode non-UTF-8 charsets — but only parse og: tags. New code should use opengraph_fetch and OpengraphCache, which also parse Twitter Card, JSON-LD and HTML meta fallbacks.
UI Integration
Fallback UI: Always provide fallback UI for cases where OpenGraph data might be missing
Loading States: Show appropriate loading indicators while data is being fetched
Error States: Handle error states gracefully with user-friendly messages
Contribution
Contributions are welcome! If you find any issues or have suggestions for improvements, please feel free to open an issue or submit a pull request on the GitHub repository.