Free tools Windows power users keep installed
One-click scans. No signup required.
Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.
Generate an Open Graph image in C# by drawing it with a .NET graphics library, encoding it as an image file, publishing that file at a stable HTTPS URL, and pointing your page’s metadata at it with og:image. Open Graph defines the metadata that identifies an image; it does not prescribe how to create one. This guide uses SkiaSharp for a complete ASP.NET Core example and explains the publishing and preview details that are easy to miss.
What an Open Graph image needs
The Open Graph protocol lets a web page become a rich object in a social graph. Its og:image property identifies an image resource that a platform can fetch for a page preview; your C# code is responsible for creating and serving that resource. See the Open Graph protocol.
A useful image is not enough by itself. The image must be reachable by the social platform’s crawler, and the page’s HTML response must contain the metadata. For each page, use a descriptive, page-specific image URL where practical, rather than pointing every page at an unrelated generic graphic.
Quick wins for a faster PC:
Repair Windows errors before they cause bigger problemsFix Now →Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Clear out junk files and repair common Windows errorsFree Scan →Metadata fields to emit
The protocol defines og:image and structured properties for image MIME type, width, height, secure URL, and alternative text. When you specify og:image, the protocol says you should also specify og:image:alt. The alt value should describe what the image communicates, not merely say “image.”
#1 Best Overall
og:image: absolute URL of the image.og:image:secure_url: HTTPS URL for the image, when supplied separately.og:image:type: MIME type such asimage/pngorimage/jpeg.og:image:widthandog:image:height: pixel dimensions of the image.og:image:alt: descriptive text for the image.
Choose a .NET rendering approach
SkiaSharp is a .NET 2D drawing API. Its documented workflow creates a drawing surface and canvas, draws into it, and encodes the pixel data; supported encodings documented by Microsoft include JPEG, PNG, and WebP, including output to a stream. The example below uses PNG because it is straightforward for text and graphics. Check the current SkiaSharp API documentation for the version and target framework you deploy.
SkiaSharp or ImageSharp?
ImageSharp is another .NET 2D graphics library. The available project information does not establish a reliable performance or feature winner for Open Graph generation, so choose based on the drawing and text APIs your design needs, output formats, target operating systems and containers, licensing, and package constraints. Verify those details in the projects’ current primary documentation before committing to a dependency; the ImageSharp repository identifies the project but is not a basis for an unsupported head-to-head claim.
Choose dimensions for the destinations
A secondary overview suggests 1200 × 630 pixels (about 1.91:1) as a practical size for major social previews. Treat it as a starting point, not a universal or permanent rule: destination platforms can change recommended dimensions, file-size limits, accepted formats, and cropping behavior. Consult the current official guidance for each platform you care about before relying on an exact specification. The secondary reference is OpenGraph.dev.
Rank #2
Build a PNG in C# with SkiaSharp
Install SkiaSharp into the project that will render the image. For an ASP.NET Core application, for example:
dotnet add package SkiaSharp
The following .NET example creates a 1200 × 630 PNG, draws a background and title, and writes it to disk. It uses SkiaSharp’s surface/canvas and PNG encoding workflow. The exact package version is intentionally not pinned here; select and test a current version compatible with your target framework and deployment environment.
using SkiaSharp;
const int width = 1200;
const int height = 630;
var outputPath = Path.Combine("wwwroot", "og", "article-example.png");
Directory.CreateDirectory(Path.GetDirectoryName(outputPath)!);
using var surface = SKSurface.Create(new SKImageInfo(width, height));
var canvas = surface.Canvas;
canvas.Clear(new SKColor(20, 35, 65));
using var accent = new SKPaint
{
Color = new SKColor(87, 190, 255),
IsAntialias = true
};
canvas.DrawRoundRect(new SKRect(72, 72, 1128, 558), 28, 28, accent);
using var panel = new SKPaint { Color = new SKColor(20, 35, 65), IsAntialias = true };
canvas.DrawRoundRect(new SKRect(82, 82, 1118, 548), 22, 22, panel);
using var titlePaint = new SKPaint
{
Color = SKColors.White,
TextSize = 64,
IsAntialias = true,
Typeface = SKTypeface.FromFamilyName("Arial", SKFontStyle.Bold)
};
canvas.DrawText("Generate Open Graph Images", 112, 250, titlePaint);
using var subtitlePaint = new SKPaint
{
Color = new SKColor(205, 220, 240),
TextSize = 32,
IsAntialias = true
};
canvas.DrawText("A C# implementation guide", 114, 315, subtitlePaint);
using var image = surface.Snapshot();
using var data = image.Encode(SKEncodedImageFormat.Png, 100);
using var stream = File.Create(outputPath);
data.SaveTo(stream);
Console.WriteLine($"Wrote {outputPath}");
This is intentionally a minimal drawing example, not a complete layout engine. Long or user-supplied titles need wrapping and clipping logic: measure text, choose line breaks, constrain the number of lines, and reduce font size or truncate gracefully when the title does not fit. Choose a font available in the production container; relying on a workstation font that is absent in Linux can change rendering or produce unexpected fallback. For designs with logos or branded elements, include the assets in deployment and load them from known application paths.
Write to a stream or object storage
For an ASP.NET request or background job, you can encode to a stream instead of a local file, then send those bytes to the storage service you use. SkiaSharp’s image encoding APIs support stream output. Keep rendering separate from request handling if image generation is expensive or must be reused. A stable image URL is essential; a temporary local path or private storage URL will not work for a crawler that cannot access it.
The Tool Desk
Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →Publish the image and add page metadata
- Save the image in a location that is publicly reachable over HTTPS, such as a static-file directory served by your application or public object storage.
- Confirm the deployed URL returns the image itself without requiring a login, session cookie, or browser-only JavaScript. A crawler must be able to fetch it directly.
- Put the Open Graph tags in the page’s HTML head. In ASP.NET Core MVC or Razor Pages, render these values in the shared layout or page-specific head section, using the current page’s image URL and descriptive alt text.
- Ensure the dimensions and MIME type in the tags match the actual encoded file. Do not label a PNG as JPEG or advertise dimensions that differ from the generated image.
Example page metadata:
<meta property="og:title" content="Generate Open Graph Images in C#" />
<meta property="og:type" content="article" />
<meta property="og:url" content="https://example.com/guides/csharp-og-images" />
<meta property="og:image" content="https://example.com/og/article-example.png" />
<meta property="og:image:secure_url" content="https://example.com/og/article-example.png" />
<meta property="og:image:type" content="image/png" />
<meta property="og:image:width" content="1200" />
<meta property="og:image:height" content="630" />
<meta property="og:image:alt" content="A dark blue card titled Generate Open Graph Images, with the subtitle A C# implementation guide." />
Replace the example domain and page values with the canonical URL and metadata for the actual page. If your framework generates metadata dynamically, inspect the raw HTTP response or rendered HTML source to confirm the tags are present in the server response, not only added later by client-side JavaScript.
Or skip the browser setup
If the job is capturing a website as an image rather than drawing a custom social card, ScreenshotNeo is a website screenshot API and MCP server for developers. It takes a URL and returns an image or PDF. A one-call request looks like this:
Rank #4
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
See the ScreenshotNeo API documentation for request options and output configuration. Cookie banners, popups, and chat widgets are removed before the shot; bot checks, blank pages, and failed loads are never billed. Its MCP server lets AI agents use screenshot tools. The free plan includes 1,000 screenshots a month with no card, and paid plans start at $5 for 3,000. Sign up for free.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Operational considerations
Rendering frequency and caching
If the image depends only on a page title, brand colors, or other stable content, generate it when content is published or updated and keep the result at a stable URL. Regenerating it on every page request wastes CPU and can make output inconsistent. When an image changes but its URL does not, a platform may continue showing its cached copy; using a versioned image URL when content changes can make the new asset discoverable, though each platform controls its own refresh behavior.
Formats and deployment
PNG and JPEG are conservative starting formats; SkiaSharp also documents WebP encoding. Match the format to the intended platform’s current support and the nature of the image: sharp text and flat graphics often suit lossless output, while photographs may benefit from a lossy format. Validate the actual response content type and file size in production. Image dimensions alone do not guarantee a platform accepts the file.
For container or cross-platform deployments, test the rendering path in the same runtime environment used in production. Native dependencies, font availability, memory limits, and package versions can differ from a developer workstation. For large batches, bound concurrency and dispose of surfaces, images, paints, and streams; the example uses using declarations for these disposable objects.
Best Value
Troubleshoot missing or incorrect previews
The preview has no image
- Check that
og:imageis present in the HTML response’s head and contains an absolute HTTPS URL. - Open the image URL without being logged in. A 404, redirect loop, access denial, or HTML error page means the crawler cannot use the asset.
- Check that robots rules, firewall rules, or hosting configuration are not blocking the platform’s crawler.
- Confirm that the HTML is server-rendered or otherwise visible to the crawler; do not assume client-side metadata injection will be processed consistently.
The image is broken, wrong, or cropped
- Verify the file’s bytes, MIME type, and declared dimensions agree. A tag claiming
image/pngcannot fix a JPEG file. - Check the image at the destination’s current recommended aspect ratio and safe text area. A platform may crop a valid image differently from your own preview.
- Inspect font fallback and title wrapping in the production environment if the generated card differs from local output.
Changes do not appear immediately
Social platforms cache page metadata and images differently. Updating the source image does not guarantee every preview refreshes immediately. Use the destination platform’s current inspector or debugger procedure to request a re-fetch where offered, and consider publishing changed assets at versioned URLs. Exact cache tools and procedures are platform-specific and can change.
FAQ
Does Open Graph generate the image?
No. Open Graph defines metadata fields such as og:image that point to an image. Your C# application or another rendering service must create and host the file.
Recommended Free Tools
Can I use WebP?
SkiaSharp documents WebP encoding, but acceptance depends on the destination platform. Confirm current format support before selecting it for a shared preview.
Should every page use the same image?
It can, but page-specific imagery and alt text make the preview more relevant when the content differs. Use a shared card only when it accurately represents the pages that reference it.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

