Image sources
src is either a local path or an http(s):// URL, up to 1000 characters.
Local files
Section titled “Local files”A relative path is looked up in this order, first match wins:
- the
publicdisk —Storage::disk('public'), usuallystorage/app/public storage_path($src)— anywhere understorage/public_path($src)— anywhere underpublic/
src=products/photo.jpg # storage/app/public/products/photo.jpgsrc=images/logo.png # public/images/logo.pngA leading slash is ignored, backslashes and // are normalised. A src containing .. or a null byte, or starting with ., is rejected with 404.
The lookup always uses the public disk, regardless of the disk option (which is where the results are stored).
Remote URLs
Section titled “Remote URLs”imagepreset_url('https://cdn.example.com/photos/1.jpg', ['w' => 400]);The host must be in allowed_hosts (exact, case-insensitive match — no wildcards, subdomains are listed separately) or be the host of APP_URL:
'allowed_hosts' => [ 'cdn.example.com', 'images.example.org',],The URL is normalised first: scheme and host lowercased, an IDN host converted to ASCII, percent-encoding of the path and query made canonical.
Checks:
- only
httpandhttps; - a literal IP in a private or reserved range, and
localhost, are rejected; - redirects are not followed — a
3xxanswer counts as a failure; - non-
2xxresponses, timeouts (30 s) and connection errors give 404; - the body may not exceed
max_download_bytes(20 MB), checked againstContent-Lengthand the actual size; - the image area may not exceed
max_image_pixels.
Same-origin URLs
Section titled “Same-origin URLs”A URL on the APP_URL host whose path starts with /storage/ is read from disk instead of downloaded: https://example.com/storage/products/1.jpg is resolved like src=products/1.jpg. Other paths on your own host are downloaded over HTTP like any remote URL.
Remote sources are downloaded on every request
Section titled “Remote sources are downloaded on every request”The source is resolved before the cache is checked, so a request for a remote src downloads the image again even when the result is already cached. The downloaded copy (source_dir/dl_*) is deleted only when a new image is generated — on cache hits it stays behind.
Consequences:
- every uncached-at-CDN request for a remote image costs an outgoing HTTP request;
storage/app/imagepreset_sourcesgrows; clean it periodically withphp artisan imagepresets:clear --temp, or with a scheduled job that deletes olddl_*files.
A CDN or reverse-proxy cache in front of the endpoint (HTTP caching) keeps these requests rare. For images you control, prefer local paths.
Image-bomb protection
Section titled “Image-bomb protection”max_image_pixels (default 150 000 000) limits width × height of the source, read from the file header with getimagesize(). It applies to local and remote raster images. Formats getimagesize() can’t read (HEIC, for example) are not checked. 0 disables the check.
Missing or broken sources
Section titled “Missing or broken sources”A source that doesn’t exist, can’t be downloaded or can’t be decoded returns 404. Decoding errors are logged ([Imagepresets] makeImage failed) only when app.debug is on.