Messenger Open Graph Image Generator: Create and Validate Link Preview Images
Create the image and metadata Messenger link previews need, then validate what parsers read with practical HTML, cURL, Python, and Node.js examples.
Direct answer: A Messenger Open Graph image generator is a workflow that creates a share image and publishes the metadata that points to it. Put og:title, og:type, og:url, and og:image in the page’s <head>. Then inspect the public HTML with a parser such as Facebook’s official Object Debugger and verify the link in the Messenger context where it will be shared.
What a Messenger Open Graph image generator does
The image itself is only one part of a link preview. The Open Graph protocol defines the image URL as the representation of the page’s object in the graph. A generator should therefore help with two jobs:
- Create or export a remotely reachable image asset.
- Prepare and validate the page metadata that references that asset.
Messenger-specific dimensions, file-size limits, crop rules, and display guarantees are not established by the protocol documentation. Do not design your system around an undocumented “required” size. Create a clear image that remains understandable when displayed at different preview sizes.
Required Open Graph metadata
The protocol lists four required properties for every page:
<meta property="og:title" content="Page title">
<meta property="og:type" content="website">
<meta property="og:url" content="https://example.com/page">
<meta property="og:image" content="https://example.com/images/share-image.jpg">
Use the canonical public URL in og:url, and use an absolute HTTPS URL for og:image. The crawler must be able to request the image without a local-file path, login session, or JavaScript-only redirect.
Recommended image properties
The protocol supports structured properties for the image. Declare values that match the actual file:
<meta property="og:image:type" content="image/jpeg">
<meta property="og:image:width" content="1200">
<meta property="og:image:height" content="630">
<meta property="og:image:secure_url" content="https://example.com/images/share-image.jpg">
<meta property="og:image:alt" content="A product dashboard showing monthly usage">
og:image:alt is especially useful for accessibility and is recommended by the protocol when og:image is present. Do not copy example dimensions or MIME types unless they describe your file.
A complete page template
This document is a runnable starting point. Replace the title, URL, description, and image URL with values for your page.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Example product page</title>
<meta name="description" content="A concise description of the page.">
<meta property="og:title" content="Example product page">
<meta property="og:type" content="website">
<meta property="og:url" content="https://example.com/products/example">
<meta property="og:image" content="https://example.com/images/example-share.jpg">
<meta property="og:image:type" content="image/jpeg">
<meta property="og:image:width" content="1200">
<meta property="og:image:height" content="630">
<meta property="og:image:secure_url" content="https://example.com/images/example-share.jpg">
<meta property="og:image:alt" content="Example product dashboard">
</head>
<body>
<main>
<h1>Example product page</h1>
<p>Page content goes here.</p>
</main>
</body>
</html>
Generating the image asset
Your generator can render a template, export a static design, or create an image with an image-processing pipeline. Keep the important subject near the center and avoid small text. Apple recommends avoiding text in preview images because previews can appear at varying sizes; that guidance is for Apple Messages, but the same legibility concern is sensible when preparing Messenger assets.
Store the result at a stable, public URL. Confirm the response has an image MIME type and that the bytes are the intended file:
curl -I https://example.com/images/example-share.jpg
curl -L https://example.com/images/example-share.jpg -o /tmp/share.jpg
file /tmp/share.jpg
Multiple images and precedence
A page may declare more than one og:image. When values conflict, the first tag in document order has preference. Put the image you want selected first:
<meta property="og:image" content="https://example.com/images/primary.jpg">
<meta property="og:image:alt" content="Primary share image">
<meta property="og:image" content="https://example.com/images/alternate.jpg">
<meta property="og:image:alt" content="Alternate share image">
Keep each image’s structured properties directly after its image declaration so maintenance does not accidentally associate dimensions or alt text with the wrong asset.
Validate the generated metadata
Inspect the public HTML with cURL
curl -L -s https://example.com/products/example \
| grep -E 'property="og:(title|type|url|image|image:type|image:width|image:height|image:alt)"'
This checks the server response, not a browser’s post-JavaScript DOM. Render the tags in the initial HTML when possible.
Check with Python
import requests
from bs4 import BeautifulSoup
url = "https://example.com/products/example"
r = requests.get(url, timeout=20, headers={"User-Agent": "og-checker/1.0"})
r.raise_for_status()
soup = BeautifulSoup(r.text, "html.parser")
for name in ("title", "type", "url", "image", "image:type", "image:width", "image:height", "image:alt"):
tag = soup.find("meta", attrs={"property": f"og:{name}"})
print(f"og:{name} = {tag.get('content') if tag else None}")
Check with Node.js
const pageUrl = 'https://example.com/products/example';
const res = await fetch(pageUrl, {
headers: { 'user-agent': 'og-checker/1.0' }
});
if (!res.ok) throw new Error(`${res.status} ${res.statusText}`);
const html = await res.text();
for (const property of ['title', 'type', 'url', 'image', 'image:type', 'image:width', 'image:height', 'image:alt']) {
const re = new RegExp(`]+property=["']og:${property.replace(':', '\\:')}["'][^>]+content=["']([^"']+)["']`, 'i');
console.log(`og:${property} =`, html.match(re)?.[1] ?? null);
}
Use the official parser
The Open Graph protocol site identifies Facebook Object Debugger as Facebook’s official parser and debugger. Submit the public page there to see which tags the parser extracts, then send the URL in the intended Messenger conversation and device context. Parser access and cache-refresh behavior can change, so do not promise that one debugger action updates every existing conversation immediately.
Troubleshooting checklist
| Symptom | Likely cause | Fix |
|---|---|---|
| No image appears | og:image is missing, relative, private, or unreachable |
Use an absolute public HTTPS URL and request it with curl -I. |
| The wrong image is selected | Another image tag appears first | Inspect document order and move the intended image to the first position. |
| Image metadata is inconsistent | Declared MIME type or dimensions do not match the file | Check the downloaded bytes and update the structured properties. |
| Old preview remains | The parser or conversation is using cached data | Reinspect the public page, then verify a fresh share in the target context; allow for cache behavior you cannot control. |
| Tags are visible in source but not parsed | Malformed HTML, blocked requests, or tags added only after JavaScript runs | Return valid tags in the server-rendered <head> and test the final public response. |
| Preview title or URL is unexpected | Duplicate or conflicting properties | Keep one authoritative value for each required property and confirm og:url is canonical. |
Performance, reliability, and cost considerations
- Serve the image from a low-latency, stable host and avoid expiring signed URLs unless the crawler can fetch them during its cache window.
- Keep the HTML metadata in the first response so parsers do not depend on client-side JavaScript.
- Generate images ahead of sharing rather than rendering them synchronously for every crawler request.
- Use a deterministic filename or versioned URL when replacing an image; changing the URL is a clear way to distinguish a new asset, while parser caches may still persist.
- Monitor image requests and HTTP status codes. A successful page response does not prove that the image URL is reachable.
Or skip the browser setup
ScreenshotNeo captures a public page with one API request, which is useful when you need a visual check of the page that contains your Open Graph tags. Its capture flow accepts cookie or consent banners and removes more than 60 known consent platforms, newsletter popups, and chat widgets before the shot; each step can be turned off. Bot checks, blank pages, timeouts, failed loads, and cache hits are not billed, and the response identifies the result with X-Page-Verdict and X-Billed headers. An MCP server provides take_screenshot, get_page_info, and capture_pdf tools for AI agents.
See the ScreenshotNeo documentation for all options. The same call works from cURL, Python, or Node.js:
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://example.com/products/example -o shot.webp
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://example.com/products/example"}, timeout=90)
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://example.com/products/example' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
ScreenshotNeo includes 1,000 screenshots per month free with no card. Paid plans start at $5 for 3,000 shots, and every feature is available on every plan. Create a free ScreenshotNeo account.
FAQ
Does Messenger require a special Open Graph tag?
The protocol requirements are the standard Open Graph properties listed above. The supplied research does not establish a separate Messenger-only tag.
Can I use a local image path?
No. The value must identify a publicly reachable image URL so a parser can request it.
Should I include several candidate images?
You can, but the first image has precedence when values conflict. Declare the preferred image first.
Will changing the image file update an old conversation?
Not necessarily. Parsers and conversations may cache preview data. Validate the public page and test a fresh share.
Where should the tags be generated?
Generate them in the server-rendered HTML head or another response that the parser receives without running browser JavaScript.


