Shopify Video Not Playing on iPhone/Safari: Codec and Autoplay Fixes
A video that plays in Chrome on your laptop and shows a blank frame on an iPhone is almost always one of six things: the wrong codec, a missing autoplay attribute, an iPhone setting, a hosting problem with range requests, a script calling play at the wrong time, or a lazy-load quirk. Here is each one, how to tell which you have, and the fix.

On this page
Key takeaways
- Safari on iPhone plays H.264 video in an MP4 container reliably. WebM and un-transcoded files from other sources are the most common codec cause of a blank player.
- Autoplay on iOS needs muted, playsinline and autoplay together. Any one missing and the video sits on its first frame waiting for a tap.
- iOS Low Power Mode and the Auto-Play Video Previews accessibility setting both block autoplay on the device, and no code fixes them.
- Shopify-hosted video is transcoded for Safari automatically. Self-hosted files from Files or a third-party server need the codec, MIME type and byte-range support checked by hand.
A Shopify video that will not play on an iPhone or in Safari is nearly always one of six problems: the file is not H.264 in an MP4 container, the video element is missing muted or playsinline, the phone is in Low Power Mode, the server hosting the file does not support byte-range requests, a script is calling play outside a user gesture, or a lazy-load setting is holding the video back. The first two account for most cases, and the fix for both takes minutes once you know which one you have.
Start with one question: is the video hosted by Shopify or somewhere else? Shopify transcodes everything it hosts into formats Safari plays, so if the file is Shopify-hosted, skip to the autoplay attributes and the device settings. If it is self-hosted or linked from another server, start with the codec.
This guide goes through all six in order of likelihood, with a way to tell which one applies. If the video is missing altogether rather than present and not playing, that is a different problem, and the product video not showing guide covers it.
First: where is the file hosted?
Shopify stores video in product media and in Files, and in both cases it transcodes the upload into H.264 MP4 and streaming renditions that every browser, Safari included, can play. Shopify's hosted video accepts files up to 1 GB, 10 minutes and 4K.
Video from anywhere else is served as uploaded. That includes:
- A file on a third-party CDN or your own server, linked from a custom Liquid section.
- A page builder that hosts video on its own infrastructure.
- A video app that hosts on its own CDN. Most reputable ones transcode, but confirm it.
To check, open the page in Safari on a Mac, right-click the video and choose Inspect Element, or on Windows use Chrome and search the HTML for <video. Look at the src or source URL. A cdn.shopify.com domain means Shopify-hosted. Anything else means the fixes in the next section apply first.
Fix 1: the codec or container
Safari is strict about video formats. The combination that works everywhere is H.264 video with AAC audio in an MP4 container. Three common departures from that break playback on iPhone:
WebM. Chrome and Firefox play WebM natively. Safari's support is partial and version-dependent, and on many iPhones a WebM-only source produces a blank frame. If the page offers only a .webm source, add an MP4 source before it.
HEVC MOV files straight from an iPhone. iPhones record in HEVC (H.265) by default in a MOV container. Safari plays those, but Chrome on Android and older desktop browsers may not, so the same file can fail for customers who are not on iPhones. Export from the phone or your editor as H.264 MP4 for a file that works on every device. The phone product video guide covers export settings.
MP4 with the moov atom at the end. An MP4 stores its index (the moov atom) either at the start or the end of the file. Safari, especially on mobile, needs it at the start to begin playback before the whole file has downloaded. Files exported without the "fast start" or "web optimized" option put it at the end, and the symptom is a video that plays on desktop after a pause and never plays on iPhone.
To fix any of these, re-encode. HandBrake with the "Web Optimized" box ticked, or ffmpeg -i input.mov -c:v libx264 -c:a aac -movflags +faststart output.mp4, produces a file Safari plays. Then either replace the self-hosted file or, simpler, upload the file to Shopify's product media and let Shopify handle renditions.
A quick codec test
Open the video file's direct URL in Safari on the iPhone, not the store page. If the file plays there, the codec is fine and the problem is in the page markup or a device setting. If the direct URL shows a blank player or a broken icon, the file itself is the problem, and no attribute on the page will fix it.
Fix 2: the autoplay attributes
iOS Safari allows autoplay only for video that is muted and set to play inline. The element needs all four of these:
```html
<video autoplay muted loop playsinline preload="metadata" poster="poster.jpg">
<source src="clip.mp4" type="video/mp4">
</video>
```
mutedtells Safari there is no sound to protect the user from.playsinlinestops iOS from launching the full-screen player, which it otherwise does and which blocks autoplay.autoplayandloopdo what they say.
Miss muted and the video waits for a tap. Miss playsinline and it waits for a tap. Both must be present as attributes in the HTML, not only set later in JavaScript, because Safari checks them at the moment it decides whether to autoplay.
In Dawn's video section and product gallery these attributes are emitted by the theme's video block settings. Confirm the block's autoplay option is enabled and, if the theme has a "mute" toggle, that it is on. In a custom section, add them by hand or through Shopify's video_tag filter with autoplay: true, muted: true, loop: true, playsinline: true. The mobile autoplay guide covers the Liquid for each theme in more detail.
One more Safari detail: if the muted attribute is present but a script later sets video.muted = false before playback starts, Safari treats the video as unmuted and refuses to autoplay. Check for "unmute on load" behaviour in any sound-related app or theme script.
Fix 3: the iPhone's own settings
Three device settings stop autoplay, and no markup gets around them.
Low Power Mode. When the battery saver is on, iOS disables video autoplay entirely. The video shows its poster or first frame with a play button, and a tap starts it. This is the most common cause of "it works on my phone but not on my customer's". Anyone at under twenty percent battery who accepted the prompt is in this state.
Auto-Play Video Previews. In Settings > Accessibility > Motion, the Auto-Play Video Previews toggle, when off, blocks autoplay in Safari. Some people turn it off to reduce motion, and it stays off.
Low Data Mode. On a cellular connection or a Wi-Fi network marked as low data, Safari may defer video loading. The video appears but does not fetch its file until tapped.
You cannot detect Low Power Mode from a web page reliably, and you should not try to work around these settings. Design for them instead: always set a poster image so the paused state looks intentional, and make sure a tap plays the video. A blank black rectangle is what a missing poster looks like to a shopper in Low Power Mode, and it reads as broken.
Fix 4: the server does not support byte-range requests
This one only affects self-hosted video and it is the least obvious. Safari requests video in ranges, asking the server for specific byte spans so it can start playback and seek without downloading the whole file. It sends a request with a Range header and expects a 206 Partial Content response with Accept-Ranges: bytes and a Content-Range header.
A server that answers with a 200 OK and the whole file, or that ignores the Range header, works in Chrome and fails in Safari. The symptom is a video that never starts, or starts and cannot seek, on every Apple device while everything else is fine.
To check, open Safari's Web Inspector on a Mac connected to the iPhone, or use curl -I -H "Range: bytes=0-1" https://example.com/clip.mp4. You want HTTP/1.1 206 and an Accept-Ranges: bytes line. If you get 200 and no range headers, the host is the problem.
While you are there, check the Content-Type header. It should be video/mp4. A file served as application/octet-stream or text/plain because of a misconfigured host will not play in Safari either.
Shopify's CDN handles all of this correctly, which is another reason to upload to Shopify rather than link to a file elsewhere. Most reputable video apps do as well, but a page builder or a generic file host may not.
Symptom to cause on iPhone and Safari
| Symptom | Most likely cause | Fix |
|---|---|---|
| Blank frame, plays fine in Chrome on Android | Codec or container | Re-encode to H.264 MP4 with fast start, or host on Shopify |
| Poster shows with a play button, plays on tap | Missing muted or playsinline, or Low Power Mode | Add attributes; accept the device setting |
| Plays on your iPhone, not on a customer's | Low Power Mode, Auto-Play Video Previews, Low Data Mode | Set a poster, ensure tap-to-play works |
| Never starts, or cannot seek, only on Apple devices | Server ignores Range requests or wrong MIME type | Fix hosting headers or move the file to Shopify |
| Starts then stops, or plays only after scrolling | Lazy load or preload setting | Set preload to metadata for the visible video |
| Console shows a play() rejection | Script calling play outside a gesture | Call play only from a user event or after muted is set |
Fix 5: a script calling play at the wrong moment
Theme and app scripts often call video.play() from JavaScript, for instance when a slider changes slide or when the element scrolls into view. Safari allows that call only if the video is muted with playsinline, or if it happens inside a handler for a user gesture such as a tap.
A call outside those conditions is rejected. The video does not play and, unless the script handles the rejected promise, nothing visible happens. Open Safari's console on the page and look for an error mentioning play() and a NotAllowedError. That is this problem.
The fix depends on who wrote the script:
- Your own code. Make sure
mutedis set on the element before callingplay(), and treatplay()as a promise:video.play().catch(() => {})so a rejection does not break the rest of the script. - A theme slider. Check whether the theme has a setting to autoplay videos in sliders and whether it requires muted. Dawn's product gallery, for instance, loads video on tap by design and will not autoplay in the slider.
- An app. Report it. A video app that fails on Safari's autoplay policy has not been tested on iPhones, which is a reason to reconsider it.
Video apps built for this handle it correctly by default. SwipeReel's widgets autoplay muted and inline and load lazily, so this class of problem does not come up with them.
Fix 6: lazy loading and preload holding the video back
Lazy loading is right for video, but a few settings overshoot on Safari.
preload="none" tells the browser to fetch nothing until playback is requested. On desktop that is fine. On iPhone, combined with autoplay, Safari sometimes shows nothing at all because it has not fetched even the first frame. Use preload="metadata" on the video that is visible on load, and none for videos further down the page.
A lazy-load script that swaps a data-src for src when the element enters the viewport must also call video.load() afterwards, otherwise Safari keeps the old, empty source. If the video appears only after scrolling away and back, this is likely.
Finally, an overlay. A transparent element sitting over the video, such as a slider's navigation layer or a "tap to unmute" button that covers the whole player, absorbs the tap that would start playback. Inspect the element under your finger. If it is not the video, the tap never reached it.
Testing on a real iPhone, properly
The theme editor's mobile preview is desktop Safari or Chrome pretending to be a phone. It does not apply iOS autoplay rules, so it will play things that a real iPhone will not. Test on the device.
iPhone video test, in order
- Open the live page in Safari on an iPhone, in a private tab
- Confirm Low Power Mode is off and Auto-Play Video Previews is on for the test
- Note whether the video autoplays, shows a poster with a play button, or shows nothing
- Tap it: if it plays on tap, the file is fine and the cause is attributes or a device setting
- Open the file's direct URL in Safari: if it fails here, the cause is codec or hosting
- On a Mac, connect the iPhone and open Safari's Web Inspector for the page
- Check the console for a play() NotAllowedError
- Check the Network tab for the video request: expect 206 with video/mp4
- Repeat with Low Power Mode on to see what customers on low battery will see
Write down what you saw at each step. If you end up contacting theme or app support, that list turns "video does not work on iPhone" into a question they can answer in one reply.
When to stop fixing and use a widget
If the video is in a custom section on a self-hosted file and you have worked through codec, attributes, hosting and scripts, you are maintaining a video player by hand, and every iOS update can change the rules.
A purpose-built video widget handles all six of these. It transcodes or accepts H.264 MP4, emits muted and playsinline, serves from a CDN with correct range support, calls play only when allowed, lazy-loads with a poster, and shows a clean paused state when Low Power Mode blocks autoplay. It also puts the video in a container designed for vertical clips, with a product tag, which a theme gallery does not.
For product pages that still need the gallery video, keep it there for tap-to-play and use the widget for anything meant to autoplay. And if speed is the concern that led you to self-host in the first place, the bounce rate and video guide covers what lazy loading changes on Core Web Vitals so you can measure rather than guess.
Frequently asked questions
- Why does my Shopify video play on Android but not on iPhone?
- Usually codec or container. Chrome on Android plays WebM and a wider set of MP4 profiles than Safari does.
- Why does my video show a play button on iPhone instead of autoplaying?
- Because the video element is missing muted, playsinline or autoplay, or the iPhone is in Low Power Mode, or Auto-Play Video Previews is turned off in Settings > Accessibility > Motion.
- Does Shopify convert videos for Safari automatically?
- Yes, for video uploaded as product media or into Files through the admin. Shopify transcodes to H.264 MP4 and streaming renditions that Safari plays.
- Why does my video play on my iPhone but not on my customer's?
- The likeliest reasons are Low Power Mode, the Auto-Play Video Previews setting, Low Data Mode on their connection, or a content blocker extension in Safari. Ask them to tap the video.
- What video format should I upload to Shopify for iPhone?
- MP4 with H.264 video and AAC audio, vertical 9:16 for reels-style clips, under 1 GB and 10 minutes.
- Can I force autoplay with sound on iPhone?
- No. Safari on iOS blocks autoplay with sound in every case. The video can autoplay muted, and a tap can unmute it. Design for silent playback with captions and a tap-for-sound control.
- My video plays in the Shopify theme editor but not on the live site on iPhone. Why?
- The theme editor runs on desktop, where Safari and Chrome are more permissive.




