ScreenshotNeo

BlogHow-to

How to Debug Open Graph Tags with curl

Use curl to inspect Open Graph metadata, redirects, crawler-specific responses, and duplicate tags—and learn what a raw HTTP response cannot tell you.

By the ScreenshotNeo team4 October 20269 min read

To debug Open Graph tags with curl, fetch the exact page URL, follow redirects, and inspect the HTML response for its og: meta properties. Start with:

curl -sS -D response-headers.txt -L 'https://example.com/page' -o response.html

Then search the saved HTML:

grep -in 'og:' response.html

This shows the metadata the server returned to curl. It does not run page JavaScript or prove how a particular social platform parses or caches the page.

1. Fetch the exact URL and inspect the response

Use the same scheme, hostname, path, and query string that you intend to share. The response status and headers help distinguish a metadata problem from a redirect, access-denied response, or server error.

curl -sS -D response-headers.txt -L 'https://example.com/page?ref=share' -o response.html
cat response-headers.txt
grep -in 'og:' response.html

The -sS flags suppress the progress meter while still showing errors. -D saves response headers, -L follows HTTP redirects, and -o saves the response body. The saved headers are useful evidence when the page is not returning what you expected.

For a quick inspection without saving files:

curl -sS -L 'https://example.com/page' | grep -i 'property="og:'

To show status and headers while discarding the body:

curl -sS -D - -L 'https://example.com/page' -o /dev/null

In the returned HTML, check the actual <meta> elements and their content values. A browser’s rendered page can look correct even if the server-delivered HTML does not contain the metadata.

2. Check the required Open Graph properties

The Open Graph protocol defines four required properties for an object: og:title, og:type, og:image, and og:url. They are meta properties in the page head. og:description is optional, but generally recommended. See the Open Graph protocol specification.

Property What to verify
og:title The intended title is present and is not empty.
og:type The value describes the kind of object represented by the page.
og:image The value points to the intended image URL.
og:url The value is the permanent URL you intend to identify the object with.
og:description If present, the description is the intended summary and is not stale.
og:image:alt If og:image is specified, the protocol says to provide descriptive alt text too.

For example, the markup you expect to find might look like this:

<head>
  <meta property="og:title" content="Example page title">
  <meta property="og:type" content="website">
  <meta property="og:image" content="https://example.com/share-card.jpg">
  <meta property="og:url" content="https://example.com/page">
  <meta property="og:description" content="A short page description.">
  <meta property="og:image:alt" content="A description of the share image.">
</head>

This is an example of markup to inspect, not a claim that any live page was fetched. The protocol also defines structured image metadata such as og:image:width and og:image:height. These fields should follow the image property they describe.

3. Diagnose redirects before changing metadata

curl does not follow HTTP Location redirects by default. Add -L to follow them. During debugging, inspect the redirect chain as well as the final HTML: the requested URL may lead to a different path, hostname, or page than you expect.

curl -sS -D - -L 'https://example.com/old-path' -o /dev/null

Review the status and Location header at each redirect. Compare these two checks when useful:

# Headers from the original response, without following a redirect
curl -sS -D - -o /dev/null 'https://example.com/old-path'

# Follow redirects and inspect the final HTML
curl -sS -L -D response-headers.txt 'https://example.com/old-path' -o response.html

If the destination is unexpected, fix the redirect or share the intended canonical URL. If the destination is expected, inspect its returned markup and confirm that og:url identifies the intended object URL.

4. Compare responses by User-Agent

A server can vary its response based on the request’s User-Agent. Compare curl’s default response with one that sends the crawler identifier documented by the platform you are diagnosing:

# Default curl User-Agent
curl -sS -L 'https://example.com/page' -o default.html

# Replace this placeholder with the platform's documented crawler identifier
curl -sS -L -A 'DOCUMENTED_CRAWLER_USER_AGENT' \
  'https://example.com/page' -o crawler.html

diff -u default.html crawler.html

The -A option sets the User-Agent header. Do not assume there is one universal social crawler string: use the target platform’s current documentation for its identifier. A matching User-Agent only shows what your server returns to that request. It does not establish that the platform can reach the URL or interpret the page in exactly the same way.

5. Find duplicate and out-of-order tags

Search for every occurrence of a property, not just the first. The Open Graph protocol treats repeated properties as arrays and says the first value from top to bottom takes precedence when values conflict. A stale tag earlier in the document can therefore matter even when a correct value appears later.

grep -inE 'property="og:(title|type|image|url|description|image:)' response.html

Check that:

  • There is no unintended earlier duplicate with an outdated value.
  • Each og:image is paired with its own structured image fields where those fields are used.
  • og:image:alt describes the image rather than acting as its caption.
  • The tags are in the server-delivered HTML, not only in a browser DOM added later by JavaScript.

6. Use Python to inspect the response

This runnable example follows redirects, prints the final URL and status, and extracts Open Graph properties from the returned HTML with Python’s standard library. Install the HTTP dependency first with python -m pip install requests.

import re
import requests
from html.parser import HTMLParser

class OpenGraphParser(HTMLParser):
    def __init__(self):
        super().__init__()
        self.values = []

    def handle_starttag(self, tag, attrs):
        if tag.lower() != "meta":
            return
        attrs = dict(attrs)
        prop = attrs.get("property", "")
        if prop.lower().startswith("og:"):
            self.values.append((prop, attrs.get("content", "")))

url = "https://example.com/page"
response = requests.get(url, timeout=30, allow_redirects=True)
print("Status:", response.status_code)
print("Final URL:", response.url)
print("Redirects:", [r.status_code for r in response.history])

parser = OpenGraphParser()
parser.feed(response.text)
for prop, value in parser.values:
    print(f"{prop}: {value}")

For a crawler-specific comparison, pass a documented identifier with headers={"User-Agent": "..."} to requests.get. The parser above reports all matching tags in document order, including duplicates.

7. Use Node.js to inspect the response

This example uses Node.js’s built-in fetch. It follows redirects by default, reports the final response URL and status, and prints matching meta tags from the raw HTML with a small regular expression. For more complex or malformed HTML, use a dedicated HTML parser.

const url = 'https://example.com/page';
const res = await fetch(url, { redirect: 'follow' });
const html = await res.text();

console.log('Status:', res.status);
console.log('Final URL:', res.url);
console.log('Redirected:', res.redirected);

const tags = html.match(/<meta\b[^>]*\bproperty\s*=\s*(["'])og:[^"']+\1[^>]*>/gi) || [];
for (const tag of tags) console.log(tag);

To compare a documented crawler User-Agent, set it in the request headers:

const res = await fetch(url, {
  redirect: 'follow',
  headers: { 'User-Agent': 'DOCUMENTED_CRAWLER_USER_AGENT' }
});

8. Know what curl cannot prove

curl fetches HTTP responses. It does not execute JavaScript or follow browser-style HTML meta-refresh instructions. If a client-side app inserts Open Graph tags only after rendering, curl will not see those inserted tags in the raw response.

When the tags are missing, inspect the server-rendered HTML first. If the page relies on client-side JavaScript, arrange for the metadata to be present in the HTML response, or use the target platform’s own preview/debugging workflow to investigate its interpretation and cache. The Open Graph protocol identifies Facebook’s Object Debugger as Facebook’s parser and debugger; consult the platform’s current workflow directly, since access requirements and behavior can change.

9. Troubleshooting common failures

Symptom Likely cause What to do
No output from grep The response has no matching tags, the HTML uses a different form, or the fetched response is an error or app shell. Open response.html, check the status and final URL, and search for og: without the narrower pattern.
curl shows a redirect response Redirects are not followed unless requested. Add -L, then inspect the chain and final destination.
Unexpected page or title The shared URL redirects elsewhere, or the server varies content by request. Check status and Location headers; compare default and documented crawler User-Agent responses.
Browser shows tags but curl does not Client-side JavaScript may add them after the initial response. Inspect the raw HTML and make metadata available in the server response.
Correct tag appears but preview is stale The target platform may be using a cached interpretation. Use that platform’s own debugger or preview workflow to check its current result and refresh behavior.
Wrong value despite a correct duplicate An earlier occurrence may take precedence. Search all occurrences and remove or correct the unintended earlier property.
Image URL appears correct but preview lacks it The raw tag alone does not prove the platform can retrieve or accept the image. Check the final image URL and investigate reachability and platform-specific requirements using that platform’s tools and documentation.
curl reports a connection or TLS error The host may be unreachable from your environment, or the connection or certificate setup may be failing. Read curl’s error and response details, confirm the URL and host, then retry from an environment with access to the site.

10. Performance, reliability, and cost

For one page, curl is a small direct HTTP request. For repeatable checks, save headers and HTML so you can compare the response before and after a deployment. Set a timeout in scripts, use the final URL and status as explicit checks, and avoid treating an HTTP 200 alone as proof that the expected metadata is present.

Network access, redirects, server-side request handling, and User-Agent variation can change what you receive. A local curl response is evidence of one HTTP request from your environment, not a guarantee that a social platform can fetch the page. curl itself is command-line software; the core inspection does not require a paid screenshot service.

Or skip the browser setup

If you also need a visual capture of the page, ScreenshotNeo is a website screenshot API and MCP server for developers. Open Graph debugging still starts with the HTML response; a screenshot helps inspect the rendered appearance. One GET request can return an image or PDF. The API options include custom User-Agent, headers, cookies, JavaScript, waits, and other capture settings. See the ScreenshotNeo API documentation.

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://example.com/page -o shot.webp

ScreenshotNeo accepts cookie or consent banners and removes more than 60 known consent platforms, newsletter popups, and chat widgets before capture; each of these steps can be turned off. Bot checks and CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and responses identify the page verdict and billing status in headers. Its MCP server provides take_screenshot, get_page_info, and capture_pdf tools for Claude, Cursor, and other MCP clients. The free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 shots.

Sign up free for 1,000 screenshots a month, with no card.

FAQ

Does curl show the same page as a social crawler?

Not necessarily. You can set a documented crawler User-Agent, but network access, server behavior, and platform parsing can still differ.

Do I need a browser to check Open Graph tags?

No. curl can inspect tags already present in the HTTP response. A browser is needed to observe behavior that depends on client-side JavaScript.

Should I include og:image:width and og:image:height?

They are structured image metadata fields defined by the protocol. Include them when they accurately describe the associated image.

Why check the final URL as well as og:url?

The final URL tells you where the request landed after HTTP redirects; og:url identifies the object URL declared in the page’s metadata. They answer related but distinct questions.