diff --git a/e2e/src/web/specs/photo-viewer.e2e-spec.ts b/e2e/src/web/specs/photo-viewer.e2e-spec.ts
index 37e691625a..4871e7522c 100644
--- a/e2e/src/web/specs/photo-viewer.e2e-spec.ts
+++ b/e2e/src/web/specs/photo-viewer.e2e-spec.ts
@@ -8,12 +8,14 @@ function imageLocator(page: Page) {
 test.describe('Photo Viewer', () => {
   let admin: LoginResponseDto;
   let asset: AssetMediaResponseDto;
+  let rawAsset: AssetMediaResponseDto;
 
   test.beforeAll(async () => {
     utils.initSdk();
     await utils.resetDatabase();
     admin = await utils.adminSetup();
     asset = await utils.createAsset(admin.accessToken);
+    rawAsset = await utils.createAsset(admin.accessToken, { assetData: { filename: 'test.arw' } });
   });
 
   test.beforeEach(async ({ context, page }) => {
@@ -36,7 +38,7 @@ test.describe('Photo Viewer', () => {
     await expect(page.getByTestId('loading-spinner')).toBeVisible();
   });
 
-  test('loads high resolution photo when zoomed', async ({ page }) => {
+  test('loads original photo when zoomed', async ({ page }) => {
     await page.goto(`/photos/${asset.id}`);
     await expect.poll(async () => await imageLocator(page).getAttribute('src')).toContain('thumbnail');
     const box = await imageLocator(page).boundingBox();
@@ -44,6 +46,17 @@ test.describe('Photo Viewer', () => {
     const { x, y, width, height } = box!;
     await page.mouse.move(x + width / 2, y + height / 2);
     await page.mouse.wheel(0, -1);
+    await expect.poll(async () => await imageLocator(page).getAttribute('src')).toContain('original');
+  });
+
+  test('loads fullsize image when zoomed and original is web-incompatible', async ({ page }) => {
+    await page.goto(`/photos/${rawAsset.id}`);
+    await expect.poll(async () => await imageLocator(page).getAttribute('src')).toContain('thumbnail');
+    const box = await imageLocator(page).boundingBox();
+    expect(box).toBeTruthy();
+    const { x, y, width, height } = box!;
+    await page.mouse.move(x + width / 2, y + height / 2);
+    await page.mouse.wheel(0, -1);
     await expect.poll(async () => await imageLocator(page).getAttribute('src')).toContain('fullsize');
   });
 
diff --git a/web/src/lib/components/asset-viewer/photo-viewer.spec.ts b/web/src/lib/components/asset-viewer/photo-viewer.spec.ts
index 8690aae0c3..d90fb89c23 100644
--- a/web/src/lib/components/asset-viewer/photo-viewer.spec.ts
+++ b/web/src/lib/components/asset-viewer/photo-viewer.spec.ts
@@ -48,7 +48,7 @@ describe('PhotoViewer component', () => {
     expect(getAssetThumbnailUrlSpy).toBeCalledWith({
       id: asset.id,
       size: AssetMediaSize.Preview,
-      cacheKey: asset.checksum,
+      cacheKey: asset.thumbhash,
     });
     expect(getAssetOriginalUrlSpy).not.toBeCalled();
   });
@@ -57,11 +57,8 @@ describe('PhotoViewer component', () => {
     const asset = assetFactory.build({ originalPath: 'image.gif', originalMimeType: 'image/gif' });
     render(PhotoViewer, { asset });
 
-    expect(getAssetThumbnailUrlSpy).toBeCalledWith({
-      id: asset.id,
-      cacheKey: asset.checksum,
-      size: AssetMediaSize.Fullsize,
-    });
+    expect(getAssetThumbnailUrlSpy).not.toBeCalled();
+    expect(getAssetOriginalUrlSpy).toBeCalledWith({ id: asset.id, cacheKey: asset.thumbhash });
   });
 
   it('loads original for shared link when download permission is true and showMetadata permission is true', () => {
@@ -69,13 +66,8 @@ describe('PhotoViewer component', () => {
     const sharedLink = sharedLinkFactory.build({ allowDownload: true, showMetadata: true, assets: [asset] });
     render(PhotoViewer, { asset, sharedLink });
 
-    expect(getAssetThumbnailUrlSpy).toBeCalledWith({
-      id: asset.id,
-      size: AssetMediaSize.Fullsize,
-      cacheKey: asset.checksum,
-    });
-    // expect(getAssetThumbnailUrlSpy).not.toBeCalled();
-    // expect(getAssetOriginalUrlSpy).toBeCalledWith({ id: asset.id, cacheKey: asset.thumbhash });
+    expect(getAssetThumbnailUrlSpy).not.toBeCalled();
+    expect(getAssetOriginalUrlSpy).toBeCalledWith({ id: asset.id, cacheKey: asset.thumbhash });
   });
 
   it('not loads original image when shared link download permission is false', () => {
@@ -86,7 +78,7 @@ describe('PhotoViewer component', () => {
     expect(getAssetThumbnailUrlSpy).toBeCalledWith({
       id: asset.id,
       size: AssetMediaSize.Preview,
-      cacheKey: asset.checksum,
+      cacheKey: asset.thumbhash,
     });
 
     expect(getAssetOriginalUrlSpy).not.toBeCalled();
@@ -100,7 +92,7 @@ describe('PhotoViewer component', () => {
     expect(getAssetThumbnailUrlSpy).toBeCalledWith({
       id: asset.id,
       size: AssetMediaSize.Preview,
-      cacheKey: asset.checksum,
+      cacheKey: asset.thumbhash,
     });
 
     expect(getAssetOriginalUrlSpy).not.toBeCalled();
diff --git a/web/src/lib/components/asset-viewer/photo-viewer.svelte b/web/src/lib/components/asset-viewer/photo-viewer.svelte
index 1d7c49f107..6bc67a5257 100644
--- a/web/src/lib/components/asset-viewer/photo-viewer.svelte
+++ b/web/src/lib/components/asset-viewer/photo-viewer.svelte
@@ -6,8 +6,8 @@
   import { alwaysLoadOriginalFile } from '$lib/stores/preferences.store';
   import { SlideshowLook, SlideshowState, slideshowLookCssMapping, slideshowStore } from '$lib/stores/slideshow.store';
   import { photoZoomState } from '$lib/stores/zoom-image.store';
-  import { getAssetThumbnailUrl, handlePromiseError } from '$lib/utils';
-  import { canCopyImageToClipboard, copyImageToClipboard } from '$lib/utils/asset-utils';
+  import { getAssetOriginalUrl, getAssetThumbnailUrl, handlePromiseError } from '$lib/utils';
+  import { canCopyImageToClipboard, copyImageToClipboard, isWebCompatibleImage } from '$lib/utils/asset-utils';
   import { getBoundingBox } from '$lib/utils/people-utils';
   import { getAltText } from '$lib/utils/thumbnail-util';
   import { AssetMediaSize, AssetTypeEnum, type AssetResponseDto, type SharedLinkResponseDto } from '@immich/sdk';
@@ -68,7 +68,7 @@
     $boundingBoxesArray = [];
   });
 
-  const preload = (targetSize: AssetMediaSize, preloadAssets?: AssetResponseDto[]) => {
+  const preload = (targetSize: AssetMediaSize | 'original', preloadAssets?: AssetResponseDto[]) => {
     for (const preloadAsset of preloadAssets || []) {
       if (preloadAsset.type === AssetTypeEnum.Image) {
         let img = new Image();
@@ -77,13 +77,14 @@
     }
   };
 
-  const getAssetUrl = (id: string, targetSize: AssetMediaSize, cacheKey: string | null) => {
-    let finalAssetMediaSize = targetSize;
+  const getAssetUrl = (id: string, targetSize: AssetMediaSize | 'original', cacheKey: string | null) => {
     if (sharedLink && (!sharedLink.allowDownload || !sharedLink.showMetadata)) {
-      finalAssetMediaSize = AssetMediaSize.Preview;
+      return getAssetThumbnailUrl({ id, size: AssetMediaSize.Preview, cacheKey });
     }
 
-    return getAssetThumbnailUrl({ id, size: finalAssetMediaSize, cacheKey });
+    return targetSize === 'original'
+      ? getAssetOriginalUrl({ id, cacheKey })
+      : getAssetThumbnailUrl({ id, size: targetSize, cacheKey });
   };
 
   copyImage = async () => {
@@ -136,16 +137,18 @@
   // when true, will force loading of the original image
   let forceUseOriginal: boolean = $derived(asset.originalMimeType === 'image/gif' || $photoZoomState.currentZoom > 1);
 
-  const targetImageSize = $derived(
-    $alwaysLoadOriginalFile || forceUseOriginal || originalImageLoaded
-      ? AssetMediaSize.Fullsize
-      : AssetMediaSize.Preview,
-  );
+  const targetImageSize = $derived.by(() => {
+    if ($alwaysLoadOriginalFile || forceUseOriginal || originalImageLoaded) {
+      return isWebCompatibleImage(asset) ? 'original' : AssetMediaSize.Fullsize;
+    }
+
+    return AssetMediaSize.Preview;
+  });
 
   const onload = () => {
     imageLoaded = true;
     assetFileUrl = imageLoaderUrl;
-    originalImageLoaded = targetImageSize === AssetMediaSize.Fullsize;
+    originalImageLoaded = targetImageSize === AssetMediaSize.Fullsize || targetImageSize === 'original';
   };
 
   const onerror = () => {
@@ -168,7 +171,7 @@
     };
   });
 
-  let imageLoaderUrl = $derived(getAssetUrl(asset.id, targetImageSize, asset.checksum));
+  let imageLoaderUrl = $derived(getAssetUrl(asset.id, targetImageSize, asset.thumbhash));
 
   let containerWidth = $state(0);
   let containerHeight = $state(0);