Safari cannot play Xet-hosted embedded MP4s: CDN returns 403 "Auth failed: invalid range" for valid byte range

Embedded MP4 videos hosted on Hugging Face/Xet fail to play in Safari, while the same videos work correctly in Firefox and also play correctly when the MP4 URL is opened directly in Safari.

I encountered this on the LeRobot SO-101 documentation:

https://huggingface.co/docs/lerobot/so101

Environment

  • macOS
  • Safari 26.5.2
  • Firefox on the same Mac/network works correctly
  • Safari cache disabled during testing

Observed behavior

The embedded <video> element makes a request to:

https://us.aws.cdn.hf.co/xet-bridge-us/...

Safari sends:


GET
Range: bytes=0-3551136
Accept-Encoding: identity
Sec-Fetch-Dest: video
Sec-Fetch-Mode: no-cors
Sec-Fetch-Site: cross-site
Referer: https://huggingface.co/

The CDN responds:


HTTP 403
Content-Type: text/plain; charset=utf-8

Response body:


Auth failed: invalid range

Important detail

The affected file, Joint1_v2.mp4, is 3,551,137 bytes, so:


Range: bytes=0-3551136

is a valid request for the entire file: the last byte index is file-size minus one.

The signed Xet URL had not expired when the request was made.

Reproduction

  1. Open https://huggingface.co/docs/lerobot/so101 in Safari.
  2. Scroll to one of the embedded SO-101 assembly videos.
  3. The video does not load.
  4. Open Safari Web Inspector → Network and filter for mp4.
  5. The requests to us.aws.cdn.hf.co/xet-bridge-us/... return HTTP 403.
  6. The response body is Auth failed: invalid range.

Control tests

  • Same documentation page + Firefox + same computer/network: works
  • Direct MP4 URL + Safari: works
  • Embedded MP4 + Safari: fails
  • Safari with caches disabled: still fails

This appears to be an interoperability problem between Safari’s HTML5 media byte-range requests and the Hugging Face Xet CDN range-authentication path.

There may be some relationship to huggingface/xet-core#897, although that issue reports a different authorization error (invalid key pair id) and involved the GCP CDN, whereas this case is us.aws.cdn.hf.co returning Auth failed: invalid range.

I can provide Safari Web Inspector screenshots showing the request/response headers if useful.

For now, I couldn’t reproduce this directly since I don’t have access to an Apple environment, but:
@rajatarya


I don’t think the Range value you captured is invalid in the normal HTTP sense.

For a 3,551,137-byte representation,

Range: bytes=0-3551136

is exactly the whole representation: byte offsets are zero-based and the last position is inclusive. RFC 9110 §14.1.2 also says that if last-pos is at or beyond the current representation length, the range is interpreted as the remainder of the representation. So even a one-past-end last position would not, by itself, make an otherwise satisfiable range invalid.

That makes this part of the response especially interesting:

HTTP 403
Auth failed: invalid range

because it does not look like ordinary HTTP “requested byte range is unsatisfiable” handling. HTTP has 416 Range Not Satisfiable for that class of problem.

I also ran a small server-side control against the same public Joint1_v2.mp4. I could not reproduce Safari itself, but I could test the Hub → Xet bridge → CDN path and vary the Range request independently.

The result was useful: from my Colab/Linux environment, Hugging Face routed the file to us.gcp.cdn.hf.co, and the same closed full-file range that failed for you through us.aws.cdn.hf.co worked normally:

Your Safari embedded request:
us.aws.cdn.hf.co
Range: bytes=0-3551136
→ 403  Auth failed: invalid range

My server-side control:
us.gcp.cdn.hf.co
Range: bytes=0-3551136
→ 206 Partial Content

I also tried the visible media-request headers from your capture (Accept-Encoding: identity, Sec-Fetch-Dest: video, Sec-Fetch-Mode: no-cors, Sec-Fetch-Site: cross-site, and the HF Referer), and that still returned 206.

So at this point I would move “Safari generated an intrinsically invalid Range” fairly far down the list.

The most informative distinction now looks like:

Do the failing Safari path and the two successful paths actually reach the same CDN host / POP, and do they send the same sequence of Range requests?

HF’s current download documentation explicitly lists both us.aws.cdn.hf.co and us.gcp.cdn.hf.co as CDN endpoints, so the AWS/GCP difference is a real delivery-path distinction rather than just cosmetic hostname variation.

The first comparison I would make

You already have three very good controls:

Path Result
Safari + embedded <video> fails
Safari + direct MP4 works
Firefox + embedded <video> works

For those three, the highest-value fields seem to be:

final CDN hostname
x-hf-cdn-pop       (if present)
HTTP version
Range requests immediately before the failure
status
Content-Range
Content-Length
Accept-Ranges

And, if they are readily visible:

X-Cache
Via
ETag
Last-Modified
If-Range
request / trace IDs

In particular, I would look at the sequence, not only the final failing request. Safari/WebKit media loading is known to use small byte-range probes such as bytes=0-1; WebKit developers have explicitly noted that such a request is not inherently incorrect and that a range-capable server should normally answer it with 206. See WebKit bug 284443.

So, for example, this would be a very informative trace:

bytes=0-1         → 206
bytes=0-3551136   → 403

because it would point much more specifically at handling of the second request than at video decoding or Safari’s use of Range requests in general.

Why I think the reported Range itself is OK

The byte-range rules are fairly unambiguous here.

From RFC 9110 §14.1.2:

  • byte offsets start at zero;
  • last-pos is inclusive;
  • an integer range is satisfiable when first-pos is less than the current representation length;
  • if last-pos is omitted or is greater than or equal to the representation length, it is interpreted as the remainder of the representation.

For a length of:

3,551,137 bytes

the final byte is therefore:

3,551,136

and this is an exact full-file closed range:

bytes=0-3551136

There is also an important distinction between an HTTP-invalid range expression and an unsatisfiable range.

For example:

bytes=100-50

is invalid because the last position is below the first.

But a syntactically valid range whose first byte is already beyond the representation is normally an unsatisfiable range. HTTP defines 416 Range Not Satisfiable for that case, and a byte-range 416 response should normally include something like:

Content-Range: bytes */3551137

That distinction also showed up cleanly in my control test: when I deliberately requested the first byte after the file,

Range: bytes=3551137-3551137

the CDN returned 416.

So the observed:

403
Auth failed: invalid range

looks like a different failure class — perhaps an authorization, validation, bridge, or edge-layer check involving the Range — rather than straightforward RFC byte-range satisfiability.

I would still avoid calling that an HF/CDN bug with certainty from outside the service, because an internal validator could be checking something other than the public object’s apparent byte length.

What I could and could not reproduce without Safari

I used the same public Joint1_v2.mp4, obtained a fresh Hub resolve redirect, then reused the same final signed CDN URL while changing only the Range/header shape.

The route selected for my environment was:

huggingface.co/resolve/...
        ↓
us.gcp.cdn.hf.co/xet-bridge-us/...

The target tests were:

Request Result
no Range 200
bytes=0- 206
bytes=0-1 206
bytes=0-3551136 206
bytes=0-3551137 206
bytes=3551136-3551136 206
bytes=3551137-3551137 416

That bytes=0-3551137 result is also consistent with RFC 9110: when the end exceeds the representation length but the first position is valid, the server can simply return through the actual final byte.

I then used another fresh signed URL and sent:

bytes=0-1

followed by:

bytes=0-3551136

using the visible media-related headers from your Safari capture.

That produced:

206
206

I also did small 0-1 / 0- controls against sibling LeRobot MP4s, and those succeeded as well.

So this is a negative control, not a Safari reproduction:

  • it shows the exact full-file closed range can work through the Xet bridge/CDN path;
  • it makes a universal xet-bridge rejection of 0-(size-1) less likely;
  • it does not prove that Safari is doing nothing different;
  • and it does not prove that GCP and AWS edges are configured identically.

In fact, the different CDN route is probably the most interesting thing that fell out of the test.

Why I would separate the Xet bridge path from native Xet downloads

One terminology/detail that may help future debugging:

the browser path here should not automatically be treated as the native Xet download protocol used by hf_xet.

HF’s current Backward Compatibility with LFS documentation says that non-Xet-aware clients are supported through a Git LFS bridge. A native Xet-aware client receives reconstruction information from CAS, whereas a legacy/web client can receive a single URL through the bridge.

The Xet file-ID documentation makes the same distinction when following a normal Hub resolve redirect.

That matters because native Xet has its own range-oriented mechanisms and signed download protocol, but I don’t think it is safe to take those internal/native-Xet rules and assume they directly explain what an HTML <video> request to:

.../xet-bridge-us/...

is doing.

For this case, I would describe the boundary more conservatively as something like:

Safari media loader
    ↓
Hub resolve redirect
    ↓
legacy / HTTP-compatible Xet bridge path
    ↓
selected CDN / edge

and try to identify which boundary first differs between the successful and unsuccessful cases.

A nearby Xet/CDN precedent — similar failure shape, not necessarily the same bug

Your link to xet-core#897 still looks relevant to me, but mainly as a failure-domain precedent, not as evidence of the same root cause.

That issue reported a different error:

403
Auth failed: SignatureError: invalid key pair id

and involved the GCP CDN rather than the AWS CDN.

The useful part of that report is the control structure.

For the same requested data/range:

transfer.xethub.hf.co  → 206
us.gcp.cdn.hf.co       → 403

and the selected fetch hosts differed depending on the client’s network/egress environment.

It also reported that switching away from the native Xet client did not necessarily avoid the failure, because the compatibility/bridge path could still be redirected to the affected CDN.

So I would not infer:

#897 == this Safari problem

but it does show that:

“same underlying HF/Xet-backed data, but one selected delivery endpoint accepts the request and another rejects it”

is a failure shape that has occurred before.

That is why I think comparing the final host/POP for Safari embedded, Safari direct, and Firefox embedded is probably higher-value now than changing the MP4 itself.

As of this reply, #897 is closed, although I do not see a public fix explanation there that would justify assuming the present issue is the same resolved problem.

Another useful HF Range precedent, but again a different bug

There is also a fairly detailed 2026 investigation in huggingface_hub PR #3778.

That was not this failure either.

In that case, a resumed HTTP download sent a Range request, but CloudFront returned 200 with the whole gzip-compressed object rather than 206, and the client appended it to already-downloaded data.

What makes the investigation useful here is the method: the HF-side debugging correlated the Range-bearing requests with a specific edge POP and the actual CDN request logs.

So fields such as:

x-hf-cdn-pop
request ID
final host
Range
status

could be particularly useful if somebody with access to the CDN/bridge logs looks at this later.

That PR also gives us a useful negative comparison. Your Safari request explicitly has:

Accept-Encoding: identity

whereas the #3778 failure involved Range behavior in combination with gzip encoding. So I would not currently merge that old bug with this one.

A small timing / infrastructure note

There is one current operational detail worth recording, although I would treat it as correlation only.

The Hugging Face status page shows an AWS CDN (Singapore) incident on August 7, 2026, which was resolved at 23:14 UTC. The status update says downloads from that region were stable after the fix and that additional capacity was added.

At the time I checked, both the AWS CDN and Google Cloud CDN are reported Operational.

This does not establish a connection to this report:

  • that incident was an elevated-error/download incident, not specifically this 403 Auth failed: invalid range;
  • we do not yet know which AWS POP served your failing request;
  • and the problem may reproduce outside that incident window.

Still, if the failing response happens to include an AWS Singapore/APAC POP identifier, the exact request time and POP would be useful context to preserve.

If it points to a completely different region, I would mostly ignore this incident and continue with the browser/CDN comparison above.

A compact decision tree

I would currently split it this way:

Safari embedded fails
│
├─ Do Safari embedded, Safari direct, and Firefox embedded
│  reach the same final CDN host / POP?
│
├─ NO
│   │
│   └─ CDN routing / edge / signing / configuration difference
│      becomes much more interesting.
│
└─ YES
    │
    ├─ Do they send different Range sequences?
    │
    ├─ YES
    │   │
    │   └─ Compare those Range shapes using the same fresh signed URL.
    │       │
    │       ├─ Only bytes=0-(N-1) fails
    │       │   └─ closed-full-range handling becomes very interesting.
    │       │
    │       ├─ Every Range request fails but no-Range works
    │       │   └─ general Range/auth handling on that route becomes interesting.
    │       │
    │       └─ All curl controls succeed
    │           └─ browser request chronology / connection state /
    │              protocol / hidden header differences become more likely.
    │
    └─ NO, essentially the same Range too
        │
        ├─ Same host but different POP / edge IDs
        │   └─ edge/configuration difference remains plausible.
        │
        └─ Same host + same POP + same Range,
            Firefox works and Safari fails
            └─ Safari/media-loader-specific request context becomes
               substantially stronger.

There is another useful branch if any response exposes a surprising representation length:

Content-Range: bytes .../<unexpected size>

If the CDN/bridge believes the object has a different length from 3,551,137 bytes, then a stale or mismatched representation/object metadata path would deserve a much higher ranking.

At the moment I would keep that below the CDN/request-path hypotheses because the same Joint1_v2.mp4 works normally through the GCP bridge route in my control.

Things I would not change yet

I would personally postpone these as fixes:

  • re-encoding the MP4;
  • changing codec;
  • adding faststart;
  • changing MIME handling;
  • replacing the <video> element with JavaScript fetching;
  • assuming CORS is the root cause.

MP4 layout can absolutely affect which ranges a media engine chooses to request, so it can matter indirectly.

But in the captured failure, the request reaches the CDN and receives:

403
Auth failed: invalid range

before media decoding becomes the interesting part.

And the same MP4 can be opened directly in Safari, which is already a useful control against a simple “Safari cannot decode this file” explanation.

Similarly, Sec-Fetch-Mode: no-cors on a media fetch is not automatically suspicious. Native media fetching and JavaScript fetch() also do not have exactly the same security/request behavior, so replacing one with the other too early could change the experiment rather than isolate the original failure.

I would first preserve the failing case and compare its network path.

If a same-signed-URL test becomes useful

If the successful and failing browser captures still leave ambiguity, a very small curl matrix against one fresh final signed URL can separate several possibilities without needing to reproduce Safari:

# Conceptually:

GET with no Range

Range: bytes=0-
Range: bytes=0-1
Range: bytes=0-3551136

Using exactly the same final signed URL matters: otherwise URL generation/routing differences get mixed into the Range comparison.

If useful, an intentionally unsatisfiable control is:

Range: bytes=3551137-3551137

for this 3,551,137-byte object.

Expected interpretation would be roughly:

Observation What it would favor
0- succeeds, exact 0-(N-1) gets the 403 closed full-range validation edge case
all Range forms get 403, no-Range succeeds general Range/auth interaction
all forms return 206/200 normally something specific to browser path/sequence/edge
truly out-of-range request gets normal 416 while Safari range gets 403 separate HTTP range-vs-auth failure classes
behavior changes across CDN hosts/POPs routing / edge configuration

One practical caution: I would avoid posting the full signed CDN URL publicly. The hostname, sanitized path shape, relevant headers, POP/request IDs, status and response body should normally carry the useful debugging information without publishing the temporary signature.

Also, use a freshly generated URL for this sort of comparison so URL expiration is not introduced as another variable.

So my current ranking would be approximately:

  1. an interaction between Safari’s media request pattern and the particular AWS CDN/bridge path it reaches;
  2. a CDN/POP/routing-specific validation or authorization difference;
  3. some less-visible Safari request-context difference that the simple curl reproduction did not copy;
  4. representation/metadata mismatch on one path;
  5. much lower: generic CORS, codec, MP4-format, or simple off-by-one explanations.

The key negative result for me is that the exact reported range is accepted as a normal 206 when the same Xet-backed object is delivered through the GCP CDN, while an actually unsatisfiable control gets the expected 416.

So if the Web Inspector screenshots are easy to capture, I think the most reusable ones would be the successful and failing requests side-by-side, including the request immediately before the failure and the final hostname / x-hf-cdn-pop / Range / response headers. That should tell us whether the next branch is primarily browser behavior or delivery-path behavior, without needing to guess at the internal root cause first.

Sorry, not sure, what is going. Here is another mp4 that has a problem rendering in Safari. It renders fine in Firefox.

https://cdn-uploads.huggingface.co/production/uploads/62e34a12c9bece303d146af8/Cm3I6kidy2YP5nu3un7XP.mp4

Nice! We may have found an interesting separate issue:


I think this new example is probably worth keeping separate from the original Xet/403 Auth failed: invalid range case for now.

The visible symptom is similar — “Safari does not play an HF-hosted MP4, Firefox does” — but the failure shape is quite different:

Original case
-------------
embedded <video>
→ Hugging Face resolve
→ xet-bridge / CDN
→ Range request
→ 403 Auth failed: invalid range


This new example
----------------
direct navigation to an MP4
→ cdn-uploads.huggingface.co
→ HTTP 200
→ Safari's built-in media document/player does not render/play it

After looking at the headers and probing that exact public MP4, the strongest clue in the second case is currently this response header:

Content-Security-Policy: default-src 'none'; sandbox

There is a surprisingly close historical WebKit issue for exactly that combination: WebKit #225865 — “CSP sandbox policy header disables built-in media player”.

That old report described:

  • an audio/video file served with Content-Security-Policy: sandbox;
  • Safari failing to play it;
  • Firefox working;
  • Safari logging that script execution was blocked because the document was sandboxed without allow-scripts;
  • sandbox allow-scripts working around it.

WebKit later marked that issue as a duplicate of #223422 — “CSP headers can block default <video> controls”, so I would not say “this is definitely that old Safari bug.” But the match is close enough that I think it is now the first branch I would test.

There is also an important subtlety here: opening an MP4 directly is not necessarily the same browser path as playing the same URL in an ordinary <video> element.

The HTML Living Standard’s “Loading media documents” algorithm says that when a browser navigates directly to a video resource, the user agent creates an HTML Document, inserts a video host element for the media, and may add its own content/scripts/styles for the media UI.

That distinction turns out to matter in real browser bugs.

Mozilla had an extremely similar Firefox regression: Bug 1781063 — “MP4 file served with Content-Security-Policy: sandbox doesn’t play in Firefox when loaded as document”.

One of the Firefox developers summarized the important distinction as:

video as a document vs HTMLMediaElement

and the bug affected media loaded as a document, while normal video loaded from HTML followed a different path. Firefox fixed that in the 104–106 timeframe.

So the lowest-cost Safari comparison may actually be simpler than any custom repro:

  1. open the MP4 URL directly in Safari;
  2. open the model card where the exact same URL is embedded in a normal <video> element.

The model card contains:

<video controls autoplay
  src="https://cdn-uploads.huggingface.co/production/uploads/62e34a12c9bece303d146af8/Cm3I6kidy2YP5nu3un7XP.mp4">
</video>

If the result is:

direct MP4 URL       → fails
embedded <video>     → works

then I would move the media-document + CSP sandbox branch very high.

I also ran a small independent probe against this exact MP4, mostly to eliminate some more ordinary explanations.

The current file looks like this:

Property Observation
Size 513,769 bytes
Container MP4
Video codec H.264
Codec tag avc1
Profile High
Pixel format yuv420p
Resolution 848 × 480
Frame rate 10 fps
Audio none
Full FFmpeg decode succeeds
CSP default-src 'none'; sandbox
moov location after mdat

The CDN’s byte-range behavior also looked normal from my test environment:

Range: bytes=0-1
→ 206

Range: bytes=0-513768
→ 206

Range: bytes=0-513769
→ 206
   Content-Range ends correctly at 513768

Range: bytes=513768-513768
→ 206

Range: bytes=513769-513769
→ 416

So for this second example, I would currently rank these roughly as:

1. CSP sandbox × Safari/WebKit media-document path
2. a current WebKit regression / closely related media-document bug
3. MP4 layout as a secondary trigger/control
4. some other Safari media-pipeline issue
5. simple codec incompatibility
6. ordinary CDN Range handling
7. Xet

The fact that it is already conventional H.264 + avc1 + yuv420p, fully decodes in FFmpeg, and gets normal 206/416 Range responses makes the simple codec/corrupt-file/Range explanations less attractive.

Why the direct-navigation / media-document distinction looks important

The HTML specification’s media-document path is worth spelling out because it makes this look less mysterious.

When you navigate directly to a media resource, the browser creates a document around it. For video, the spec describes creating a video host element and setting its src to the media resource. The browser may also add its own content, styles, scripts, controls, etc.

So conceptually:

direct navigation to foo.mp4

does not have to mean:

"decode foo.mp4 directly with no document machinery"

It can mean:

generated MediaDocument
└── browser-created <video src="foo.mp4">
    └── browser/UA media controls

That is precisely the kind of boundary where a document-level sandbox can collide with browser-created media UI.

There is even an older WebKit issue that makes this implementation concern explicit: WebKit #147734.

That bug was about a different sandbox source (Content-Disposition: attachment, not CSP), so it is not the same bug, but the WebKit developer’s explanation is very relevant: a MediaDocument itself cannot provide scripts, while the browser still needs script in its user-agent shadow DOM for the controls to function.

That makes a CSP/media-document interaction technically plausible without requiring the MP4 itself to contain anything unusual.

Historical WebKit evidence

The closest old Safari/WebKit report I found is #225865.

Its reproduction was essentially:

audio/video response
+
Content-Security-Policy: sandbox

Safari:
video does not play

Firefox:
works

The reporter also saw a Safari console message equivalent to:

Blocked script execution ... because the document's frame is sandboxed
and the 'allow-scripts' permission is not set.

and reported this workaround:

Content-Security-Policy: sandbox allow-scripts

WebKit later said the behavior was not desired and marked it as a duplicate of #223422.

I would be a little careful with interpreting that history, though.

It does not necessarily mean that every possible sandbox + MediaDocument interaction was permanently solved by one patch. The #223422 work was around browser-provided media controls being incorrectly constrained by page CSP, and WebKit has had several related bugs around UA media controls and sandbox restrictions.

There is also a more recent WebKit-family datapoint in #221622.

That issue originally concerned bad HTTP Range behavior in the WebKitGTK/GStreamer port, so again it is not a Safari/macOS bug and not the same case.

But a 2024 comment is interesting: after the test server had been fixed to return proper 206 responses, one MP4 still failed. Its response had a restrictive CSP including sandbox, and the inspector reported blocked script execution because allow-scripts was absent. The commenter reported that playback worked after changing WebKit’s script-execution check.

That does not prove anything about current Safari, but it does show that sandboxed media documents have remained a nontrivial implementation boundary even after the older Safari fix.

Cross-engine precedent: Firefox had almost the same class of bug

Mozilla Bug 1781063 is useful because it shows this is not a uniquely strange Safari concept.

Firefox had a regression where:

MP4 served with:
Content-Security-Policy: sandbox

could fail when loaded as a document.

The same media could behave differently when loaded as a normal HTML media element.

The developer explicitly corrected the diagnostic terminology from approximately:

top-level load vs HTML

to:

video as a document vs HTMLMediaElement

because that was the actual implementation boundary.

Firefox’s media-document implementation was reusing the original document response as the resource response for the generated media host element, and sandbox/response-tainting logic interacted badly with that path.

Again, that Firefox implementation detail should not be projected onto Safari.

But it makes this diagnostic split much less speculative:

direct media document
vs
ordinary embedded <video>

is a real cross-browser failure boundary.

What the probe suggests about codec, corruption, and HTTP Range

I wanted to make sure the sandbox clue was not distracting us from a more boring MP4 problem.

The source probes as:

codec_name:       h264
codec_tag_string: avc1
profile:          High
pix_fmt:          yuv420p
width:            848
height:           480
avg_frame_rate:   10/1
audio:            none

and FFmpeg can decode the complete file without error.

That does not prove every Safari media pipeline must accept it, but it makes a simple “this is some weird unsupported MP4 codec” explanation substantially weaker.

The live CDN also advertises Range support and responded conventionally to all of the controls I tried.

Most importantly, this:

bytes=0-513768

returned 206, while this truly unsatisfiable request:

bytes=513769-513769

returned 416.

So unlike the original Xet/AWS case, I do not currently see an HTTP Range anomaly in this second example.

The MP4 is not faststart, but I would treat that as a secondary control

There is one ordinary media-layout wrinkle:

the top-level MP4 atoms are effectively:

ftyp
free
mdat
moov

so moov is at the end.

That can matter for progressive media loading, because a client may need to seek toward the end to obtain metadata before playback.

WebKit media developers have also noted that trailing-moov MP4 files particularly depend on usable seeking/Range behavior.

But in this case:

  • the file is only about 514 KB;
  • the CDN handles Range correctly in my probe;
  • the file fully decodes;
  • there is a very close CSP/media-document precedent.

So I would not jump directly to “re-encode with faststart.”

A better use of faststart here is as an independent diagnostic control:

original:
ftyp ... mdat ... moov

remux only:
ftyp ... moov ... mdat

without changing the encoded H.264 stream.

If CSP variants all behave identically, then comparing those two becomes useful.

A same-bytes CSP A/B test should separate this fairly cleanly

The strongest follow-up I can think of is to keep the exact same MP4 bytes and change only the document CSP.

For example:

A:
no CSP

B:
Content-Security-Policy: default-src 'none'; sandbox

C:
Content-Security-Policy: default-src 'none'; sandbox allow-scripts

Then open each URL directly in Safari.

The interesting outcomes would be:

A works
B fails
C works

→ exceptionally close to the historical WebKit #225865 failure family.

Or:

A works
B fails
C also fails

→ sandbox is still strongly implicated, but not specifically the lack of script permission.

Or:

A/B/C all fail

→ CSP drops in priority; move to layout/media-pipeline controls.

Or:

A/B/C all work

→ the difference is probably in the hosted delivery/document context rather than the media bytes alone.

One caution: I would not interpret this as “Hugging Face should just remove sandbox globally.”

CSP sandboxing can be intentional security hardening for uploaded/user-controlled content. The CSP specification explicitly gives arbitrary user attachments from message boards/email systems as an example where a restrictive sandbox is useful.

So the interesting question is not:

Is sandbox bad?

but:

Can Safari's browser-generated MediaDocument/player work correctly
when a legitimate uploaded-media response is intentionally sandboxed?

That is a much cleaner browser/platform compatibility question.

I put the probe and the A/B-test helper in public form in case anyone with Safari wants to reproduce it without rebuilding the investigation.

They use only the public MP4 and require no HF token.

They check the HTTP/CSP/Range behavior, inspect the real codec/container, perform a full FFmpeg decode, generate a remux-only faststart control and an H.264/yuv420p control, and generate a tiny local Range-capable HTTP server for the three CSP variants above.

So my current picture is:

Case 1:
Safari embedded video
→ Xet bridge / selected CDN
→ valid-looking Range
→ 403 "Auth failed: invalid range"

Case 2:
Safari direct MP4 navigation
→ cdn-uploads
→ HTTP succeeds
→ sandboxed MediaDocument/player path
→ rendering/playback problem

They may still eventually turn out to share some deeper Safari/HF interaction, but right now I think treating them as two separate branches with two different controls is safer and more useful.

For this second branch, I would start with the very cheap:

direct MP4
vs
the same MP4 embedded in the model card

comparison.

If that splits, the same-bytes CSP A/B test should tell us a lot more without changing the media itself.

I’m also experiencing the same issue with the videos on this hf space https://hsa-neurips-sup.static.hf.space/index.html

It seems the Hugging Face site wasn’t tested for compatibility in Safari and doesn’t render properly, which is frustrating, as I have all my links and bookmarks there.
I noticed some formatting issues, as well as MPEG videos not rendering.
–ziad.

Xet-hosted videos should now work in Safari.

Thank you so much for reporting the issue! Sorry for the trouble.

Thank you!

Awesome, thank you.
Also, I noticed a formatting issue. Here are two screenshots: first from Safari (images not scaled to fit) and then in Firefox (images scaled properly)
The link:
https://huggingface.co/docs/lerobot/so101?example=Linux


):

Follow-up on my previous email: Images on Firefox scaled properly: