This documentation is available as Markdown for AI agents and LLMs. See the full Markdown index or append .md to any documentation URL.

Expo Image integration

Edit page

Detect oversized images in your production app by enabling the Expo Image integration for EAS Observe.


expo-image ships an opt-in integration for EAS Observe that reports images decoded at a much larger size than the device's screen can display. Oversized images waste bandwidth and memory without improving visual quality. The integration logs an expo-image.oversized event for each one, so you can find them in production instead of auditing every screen by hand.

Prerequisites

Prerequisites

3 requirements

1.

Expo SDK 57 or later

The integration is available in expo-image version 57.0.2 and later.

2.

An app already using EAS Observe

Follow Get started to install expo-observe and create your first build. If expo-observe is not installed, the integration is a silent no-op.

3.

Expo Image installed in the app

The integration observes images loaded through expo-image. Images loaded with other libraries are not reported.

Enable the integration

Call Observe.configure() once with the expo-image integration flag at module scope, before your app mounts:

src/app/_layout.tsx
import { Observe } from 'expo-observe'; Observe.configure({ integrations: { 'expo-image': true }, });

No other setup is needed. Once enabled, the integration observes every image load automatically.

How it works

On every image load, the integration compares the image's decoded pixel size with the number of physical pixels on the device's screen. When the decoded area exceeds the screen's pixel count by more than the configured threshold, the integration logs an expo-image.oversized event with warn severity.

The decoded size that the integration sees differs between platforms for images rendered with the <Image> component:

  • On Android, the <Image> component downscales images to the component's size at decode time, so a large source displayed in a small component is usually not reported.
  • On iOS, the integration reports the source's decoded size before expo-image downscales it for rendering, so a large source displayed in a small component is still reported, even with allowDownscaling enabled.

Images loaded with the useImage hook or Image.loadAsync decode at the source's full size on both platforms by default. You can limit the decoded size with the maxWidth and maxHeight load options. This makes the reported image dimensions consistent across platforms.

Each image URL is reported at most once per app session. Deduplication uses the sanitized URL, so with the default configuration, variants of one image that differ only in their query parameters (such as rotating signed URLs) produce a single event.

Event attributes:

AttributeTypeDescription
urlstringSanitized URL of the oversized image.
urlSanitizedbooleanWhether sanitization removed part of the URL (query string, fragment, or credentials).
imageWidthnumberDecoded image width in pixels.
imageHeightnumberDecoded image height in pixels.
screenWidthnumberScreen width in points.
screenHeightnumberScreen height in points.
pixelRationumberDevice pixel ratio used to compute the screen's physical pixel count.

Events are dispatched off-device, so the integration sanitizes the image URL before reporting it:

  • The query string and fragment are removed by default, because query parameters often carry sensitive values such as signing tokens or API keys. Set the includeUrlParams option to report full URLs instead.
  • Basic-auth credentials are always removed, regardless of includeUrlParams.
  • Only http(s), file, and android.resource URLs are reported. Other schemes, such as data: or ph://, carry the image payload or a stable personal-photo identifier, so they never leave the device.

The urlSanitized attribute tells you whether sanitization changed the reported URL. URLs are reported in normalized (WHATWG) form, and normalization alone does not count as a change.

Configuration

Pass a configuration object instead of true to tune when an image is reported:

src/app/_layout.tsx
import { Observe } from 'expo-observe'; Observe.configure({ integrations: { 'expo-image': { oversizeThreshold: 2, }, }, });
  • oversizeThreshold: An image is reported when its decoded pixel area exceeds the screen's physical pixel count by more than this factor. The default is 1.5, which leaves room for a full-screen image plus 50% headroom.
  • includeUrlParams: Whether reported events include the image URL's query string and fragment. The default is false: the URL is truncated at them before it leaves the device, because query parameters often carry sensitive values such as signing tokens or API keys. Enable this only when your image URLs are safe to send off-device in full. Basic-auth credentials are always removed, regardless of this setting.

Fix oversized images

  • Serve images at a size close to their display size, for example by requesting resized variants from your image CDN.
  • When loading images with the useImage hook, set the maxWidth and maxHeight load options to downscale the image at decode time while preserving its aspect ratio.

View events

In the dashboard: open your project, navigate to Observe > Events, and select the expo-image.oversized event to see individual reports with their attributes and sessions.

From the CLI:

Terminal
# Show oversized image events
eas observe:events expo-image.oversized

For naming, severity, and attribute details shared by all events, see User-defined events.