LinkPreview is a modern Elixir package that extracts meta information from HTTP(S) URLs, perfect for building Reddit-style link previews, social media cards, and rich content displays.
- 🚀 Modern & Fast: Built with latest dependencies (Finch, Tesla, Floki)
- 🎯 Rich Metadata: Extracts titles, descriptions, images, and Open Graph data
- 🔧 Flexible: Multiple parsing strategies (HTML, Open Graph, Twitter Cards)
- 🛡️ Robust: Comprehensive error handling and optional dependencies
- 📱 Social Ready: Perfect for social media, chat apps, and content platforms
- 🧪 Well Tested: Comprehensive test suite with 67+ tests
Add link_preview
to your list of dependencies in mix.exs
:
def deps do
[
{:link_preview, "~> 1.1"}
]
end
For Elixir < 1.15, ensure link_preview is started before your application:
def application do
[extra_applications: [:link_preview]]
end
# Basic usage
{:ok, page} = LinkPreview.create("https://github.com")
%LinkPreview.Page{
title: "GitHub: Let's build from here",
description: "GitHub is where over 100 million developers shape the future...",
images: [%{url: "https://github.githubassets.com/images/modules/site/social-cards/github-social.png"}],
original_url: "https://github.com",
website_url: "github.com"
}
defmodule MyApp.LinkPreviewController do
use MyAppWeb, :controller
def create(conn, %{"url" => url}) do
case LinkPreview.create(url) do
{:ok, page} ->
json(conn, %{
title: page.title,
description: page.description,
image: get_absolute_image_url(page),
url: page.original_url,
domain: page.website_url
})
{:error, reason} ->
json(conn, %{error: "Could not fetch preview: #{reason}"})
end
end
defp get_absolute_image_url(%{images: []}), do: nil
defp get_absolute_image_url(%{images: [%{url: "/" <> path} | _], website_url: domain}) do
"https://#{domain}/#{path}"
end
defp get_absolute_image_url(%{images: [%{url: url} | _]}), do: url
end
defmodule MyAppWeb.PostLive do
use Phoenix.LiveView
def handle_event("preview_link", %{"url" => url}, socket) do
case LinkPreview.create(url) do
{:ok, page} ->
{:noreply, assign(socket, :link_preview, page)}
{:error, _} ->
{:noreply, put_flash(socket, :error, "Could not generate preview")}
end
end
end
defmodule MyApp.CachedLinkPreview do
@cache_ttl :timer.hours(24)
def get_or_create(url) do
case Cachex.get(:link_cache, url) do
{:ok, nil} ->
case LinkPreview.create(url) do
{:ok, page} = result ->
Cachex.put(:link_cache, url, page, ttl: @cache_ttl)
result
error -> error
end
{:ok, cached_page} ->
{:ok, cached_page}
end
end
end
LinkPreview supports various configuration options:
# config/config.exs
config :link_preview,
# Enable friendly string processing (default: true)
friendly_strings: true,
# Force absolute URLs for images (default: false)
force_images_absolute_url: true,
# Force URL schema (http://) for images (default: false)
force_images_url_schema: true,
# Filter small images (requires Mogrify and Temp packages)
filter_small_images: 100 # minimum dimension in pixels
For enhanced functionality, you can add these optional dependencies:
def deps do
[
{:link_preview, "~> 1.1"},
# For HTML entity decoding
{:html_entities, "~> 0.5"},
# For image size filtering
{:mogrify, "~> 0.9"},
{:temp, "~> 0.4"}
]
end
Extracts metadata from a given URL.
Parameters:
url
(String) - The URL to extract metadata from
Returns:
{:ok, %LinkPreview.Page{}}
- Success with extracted metadata{:error, reason}
- Error with reason
The main data structure containing extracted metadata:
%LinkPreview.Page{
title: "Page Title", # String | nil
description: "Page description", # String | nil
images: [%{url: "image_url"}], # List of image maps
original_url: "input_url", # String
website_url: "domain.com" # String
}
LinkPreview automatically detects and extracts from:
- Open Graph (
og:title
,og:description
,og:image
) - Twitter Cards (
twitter:title
,twitter:description
,twitter:image
) - HTML Meta Tags (
<meta name="description">
) - HTML Elements (
<title>
,<h1>-<h6>
,<img>
)
# Run tests
mix test
# Run tests with coverage
mix test --cover
# Run tests with detailed coverage
mix coveralls.html
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature
) - Commit your changes (
git commit -am 'Add amazing feature'
) - Push to the branch (
git push origin feature/amazing-feature
) - Open a Pull Request
See CHANGELOG.md for detailed changes.
Licensed under the Apache License, Version 2.0. See LICENSE for details.
Originally created by Tobiasz Małecki and Karol Wojtaszek at AppUnite. Modernized and maintained by the community.
Perfect for building:
- Social media platforms
- Chat applications
- Content management systems
- Link sharing platforms
- Rich text editors
- News aggregators