---
title: "Read EXIF data in C#"
url: https://recursiveai.org/oneimage/cookbook/read-exif-data/
description: "Read EXIF data from a photo in C#: camera make and model, date taken, orientation and the GPS position, from the headers only. Runnable code with OneImage, on any OS."
version: "1.10.4"
---

# Read EXIF data in C#

Call `Image.Identify(path).Metadata.ReadExif()`. It reads only the file headers and returns the common EXIF fields (camera, capture time, orientation, GPS position in decimal degrees), or `null` when the file has no EXIF block. The program below reads a Nikon photo with GPS from the public [exif-samples](https://github.com/ianare/exif-samples) collection.

```shell
dotnet new console -o ReadExif && cd ReadExif
dotnet add package RecursiveAI.OneImage --version 1.10.4
repo=https://raw.githubusercontent.com/ianare/exif-samples/master
curl -L -o gps.jpg $repo/jpg/gps/DSCN0010.jpg
```

OneImage needs the .NET 10 SDK. Put this in `Program.cs` and run `dotnet run`:

```csharp
using OneImage;

ExifData? exif = Image.Identify("gps.jpg").Metadata.ReadExif();
if (exif is null)
{
    Console.WriteLine("No EXIF block.");
    return;
}

Console.WriteLine($"Camera:      {exif.Make} {exif.Model}");
Console.WriteLine($"Software:    {exif.Software}");
Console.WriteLine($"Taken:       {exif.CaptureTime:yyyy-MM-dd HH:mm:ss}");
Console.WriteLine($"Orientation: {exif.Orientation}");
Console.WriteLine($"Pixels:      {exif.PixelWidth}x{exif.PixelHeight}");

if (exif.Gps is GpsPosition gps)
{
    Console.WriteLine($"GPS:         {gps.Latitude:F5}, {gps.Longitude:F5}");
}
```

```text
Camera:      NIKON COOLPIX P6000
Software:    Nikon Transfer 1.1 W
Taken:       2008-10-22 16:28:39
Orientation: 1
Pixels:      640x480
GPS:         43.46745, 11.88513
```

Latitude and longitude are signed decimal degrees: south and west are negative. `CaptureTime` is `DateTimeOriginal`, falling back to the digitized and file times; it is returned as recorded, which is usually the camera’s local clock, with no time zone applied. `Gps.Altitude` is set when the file has one.

## Other tags

`ReadExif` parses the common fields only. The raw EXIF, XMP and IPTC blocks and the ICC profile are on `Metadata`, for a dedicated parser:

```csharp
using OneImage;

ImageMetadata metadata = Image.Identify("gps.jpg").Metadata;
Console.WriteLine($"EXIF {metadata.Exif.Length} bytes, "
                + $"XMP {metadata.Xmp.Length} bytes");
Console.WriteLine($"IPTC {metadata.Iptc.Length} bytes, "
                + $"ICC {metadata.IccProfile.Length} bytes");
```

```text
EXIF 11250 bytes, XMP 4000 bytes
IPTC 0 bytes, ICC 0 bytes
```

## Limits

- **Common fields only.** Exposure, ISO, lens, maker notes and the like aren’t parsed; read them from the raw `Exif` bytes.
- **Damaged blocks:** reading is bounds-checked, so a malformed block throws `ImageFormatException` from `ReadExif`; `TryReadExif` returns `false` instead.
- **Read-only.** OneImage keeps, updates (orientation, pixel size) or removes EXIF; it doesn’t edit other tags.

GPS positions are private data: before publishing photos, [remove the metadata](https://recursiveai.org/oneimage/cookbook/remove-exif-metadata/). Metadata handling is in the [guide](https://recursiveai.org/oneimage/docs/guide/#metadata).
