Skip to main content
iVentureTeam

image_url

image_url renders a plain char field as an image, fetched by the browser straight from the URL it contains. Nothing is downloaded or stored server side, which is exactly its power and its caveat.

Siddharth JambukiyaSiddharth JambukiyaOdoo Techno-Functional Consultant
August 20, 2026Updated August 20, 20265 min read
Odoo 19 form showing the image_url widget rendering a link preview thumbnail from an external image URL stored in a char field.
Studio nameImage (on Text fields)
Technical nameimage_url
Field typeschar
Viewsform, list, kanban
Moduleweb, present in every Odoo database
Used in core4 occurrences across 2 modules: mail (link preview thumbnails), website
VersionsOdoo 20.0, Odoo 19.0, Odoo 18.0, Odoo 17.0, Odoo 16.0
No-code setupYes. In Studio, set a Text field's widget to Image.
Alternativesimage, background_image, url

What the Image URL widget does

image_url is the display twin of the binary image widget. Instead of reading image bytes from an attachment, it takes the text in a char field and hands it to the browser as an <img src>. Odoo's database never sees the pixels; only the URL string is stored.

The component keeps the URL in local state and watches the record, so the preview refreshes the moment the field value changes. If the browser cannot load the URL (dead link, blocked host, wrong content type), the onLoadFailed handler swaps the source for Odoo's standard gray placeholder image rather than showing a broken image icon.

Sizing is soft: the option or attributes become max-width and max-height inline styles, so a large source image scales down proportionally and a small one is never blown up.

What this means for your team

The widget shines wherever images already live somewhere else: a PIM or supplier catalog exposing product shots by URL, a CDN with your marketing assets, link preview thumbnails like Odoo's own mail module. You get visual lists and forms with zero storage cost, no attachment sync jobs and no duplicated binaries.

The flip side is a real operational dependency: the images render only while the remote host serves them, from the viewer's own browser. Catalogs shown to customers or auditors should not rely on third party hosts you do not control; that is when the binary image widget with real attachments is the better trade.

Setting it up in Odoo Studio (no code)

Studio exposes this widget as Image on Text fields:

  1. Open the form in Studio.

  2. Add or select a Text field that will hold the image URL.

  3. In the properties panel, set Widget to Image.

  4. Pick a Size: small, medium or large.

  5. Close Studio, paste an image URL into the field and check the preview.

What Studio cannot do here

Studio only exposes the three size presets; exact pixel bounds need the width and height attributes in XML. Studio also cannot validate what users paste: the field accepts any text, and you only discover a bad URL when the placeholder shows.

Supported options in Odoo 19

One option is declared in the 19.0 source, plus two XML attributes read by extractProps. Their precedence is the detail worth knowing: when size is set, the attributes are ignored completely.

OptionTypeWhat it does
sizearray [width, height]Bounds the rendered image. Studio offers small [0,90], medium [0,180] and large [0,270], but any [w,h] array works in XML. When set, the width and height attributes are ignored. The preset zero widths are treated as unset, so presets cap height only.
width (attribute)integerXML attribute fallback for the max width in pixels, only read when the size option is absent.
height (attribute)integerXML attribute fallback for the max height in pixels, only read when the size option is absent.

The size presets store a zero width ([0, 90] and friends), which the style getter treats as unset, so presets effectively cap only the height. Exact widths therefore require the attribute path, and the attribute path requires not using size at all.

Working examples

Odoo's own usage in mail_link_preview_views.xml, a link preview thumbnail at a fixed box:

<field name="og_image" nolabel="1" widget="image_url"
       options="{'size': [150, 150]}"/>

Attribute based sizing (only works without the size option):

<field name="logo_url" widget="image_url"
       width="120" height="48"/>

Note that custom arrays like [150, 150] work in the option even though Studio only offers the three presets.

Fallback mechanics, dead code and the 19 sizing tweak

Three source details separate this widget from what you might assume:

The fallback is one way. Once a load fails, the state holds the placeholder URL until the record data changes again; there is no retry loop. A flaky CDN therefore shows placeholders until the user touches the field or reloads.

There is dead code in 19. The component instantiates the notification service in setup and then never uses it, a leftover from an older implementation that reported load failures. Do not expect a toast when images break; the placeholder is the only signal.

The 18 to 19 sizing tweak. Until 18 the style getter only emitted max bounds when props existed. 19 adds explicit width: auto / height: auto for the missing sides, which fixed stretched images inside flex containers but can change layouts that relied on CSS sizing the img element from outside. If thumbnails moved after your 19 upgrade, this is why.

Version compatibility

VersionStatusNotes
Odoo 20.0In developmentNot released. Mechanical framework changes only in the development branch; see below.
Odoo 19.0VerifiedVerified against the shipped source; adds width and height auto for unset sides.
Odoo 18.0VerifiedSame option and attributes; style emitted only for provided bounds.
Odoo 17.0VerifiedSame behavior as 18.0.
Odoo 16.0VerifiedSame option, attributes and precedence, verified in the 16.0 source.

XML is portable from 16 through 19. Recheck any CSS that sized these images externally when moving to 19, because the widget now emits width and height auto for unset sides.

What is changing in Odoo 20

Odoo 20 is expected at Odoo Experience in Brussels, 24 to 26 September 2026. The changes below are read from the public development branch and are not final until release.

No functional changes: the option, the attributes, the precedence rule and the placeholder fallback are all identical on master. The diff is the framework wide props migration plus an internal state helper swap (useState to proxy). Even the unused notification service is still there. We will re verify this page against the released branch after the launch.

Common problems and fixes

SymptomCause and fix
The field shows a gray placeholder instead of the imageThe browser could not load the URL: dead link, host blocking hotlinks, mixed content (http image on an https page) or a non image response. Open the URL directly in a browser tab; fix the link or host the asset somewhere reliable.
width and height attributes are ignoredThe size option is set, and it takes precedence over both attributes in extractProps. Remove the size option when you need exact attribute bounds.
Images are tiny even with size mediumSizing is max based; a small source image is never upscaled. Serve larger source images; the widget will not stretch pixels.
Thumbnails shifted after upgrading to 19The 19 style getter emits width auto and height auto for unset sides, overriding external CSS that sized the img element. Set explicit bounds via the option or attributes, or adapt the CSS to target the wrapper.

Image URL widget vs the alternatives

WidgetBest forKey difference
image_urlShowing images hosted elsewhere from a URL kept in a char fieldRenders by reference, stores no binary, falls back to a placeholder on load failure
imageImages stored in Odoo with upload and resize pipelineBinary field with attachments, WebP variants and editing; heavier but self contained
background_imageRecord images as CSS backgroundsBinary based descriptor rendering a background instead of an img element
urlShowing the link itself as clickable textRenders an anchor, not the image behind it

The decision is storage versus reference: keep bytes in Odoo with the widgets below, or keep only a URL with image_url and accept the external dependency.

Frequently asked questions

What does the image_url widget do in Odoo?+
It renders a char field as an image by using the field's text as the img src. The browser fetches the picture directly from that URL; Odoo stores only the string.
Does image_url download or cache the image in Odoo?+
No. Nothing is stored server side and there is no proxying: each viewer's browser loads the URL directly. If the remote host is down or blocks the request, users see Odoo's gray placeholder.
How do I control the displayed size?+
Either options="{'size': [w, h]}" or the width/height attributes on the field tag. The option wins when both are present, and all bounds act as maximums, so images are never upscaled.
Can users upload an image with this widget?+
No. It is purely a display widget over a text URL. For uploads use the binary image widget, which manages attachments and resizing inside Odoo.
Is image_url available in Studio?+
Yes: on a Text field, set the widget to Image and pick one of the three size presets. Exact pixel bounds and custom arrays remain XML only.

Product images from your PIM, live in Odoo

Rendering catalogs by URL saves gigabytes, until hotlink blocks and dead CDNs fill your views with gray placeholders. We design image pipelines for Odoo, choosing per field between URL rendering and stored attachments, with fallbacks that hold up.

Sort out my product images

How this page was produced

This page was verified by reading the Odoo 19.0 web module source at views/fields/image_url/image_url_field.js, including extractProps precedence, the fallback constant and the style getter, then diffing the 16.0 and 18.0 branches and the public development branch. Rendering and fallback behavior were confirmed on a clean Odoo 19 database. Spotted an inaccuracy? Use our contact page.