Skip to content

Instantly share code, notes, and snippets.

@micycle1
Last active August 29, 2025 13:28
Show Gist options
  • Save micycle1/735006a338e4bea1a9c06377610886e7 to your computer and use it in GitHub Desktop.
Save micycle1/735006a338e4bea1a9c06377610886e7 to your computer and use it in GitHub Desktop.
Downloading full-size media from DeviantArt

For direct image URL, the image quality is much lower than the original upload (the resolution and size of the original upload can be found in the right sidebar). This is not the case few years ago when the original image was accessible through right click, but on 2017, Wix acquired DeviantArt, and has been migrating the images to their own image hosting system from the original DeviantArt system. They linked most of the direct images to a stripped-down version of the original images; hence the bad image quality. Below are the three different formats of direct image URLs I found:

  • URL with /v1/fill inside: this means that the image went through Wix's encoding system and is modified to a specific size and quality. In this case, you remove ?token= and its values, add /intermediary in front of /f/ in the URL, and change the image settings right after /v1/fill/ to w_5100,h_5100,bl,q_100. The definitions of the values can be found in Wix's Image Service, but basically, w_5100,h_5100 requests the width and height of the image to be 5100x5100 pixels, bl requires the baseline JPEG version, and q_100 sets the quality to 100% of the original. The reasons to have this dimension are: (1) 5100 pixels is the limit of the system; anything above it will result in 400 Bad Request. (2) according to the Wix's API:

    In case the required image is larger than the original, upscale should be enabled (lg_1) in order for a proportional upscale to be applied. If upscale is not enabled, the returned image will maintain the original size.

    Example: original URL vs modified URL. The original url has a file size of 153 KB and 1024x1280 resolution, while the modified URL has a file size of 2.03 MB and 2190x2738 resolution. The result is still not as good as the original upload (4.2 MB and 2700×3375 resolution), but this is the closest I can get

    UPDATE: for new uploads, this trick no longer works. However, the image quality can still be changed. To do this, you keep everything in the image URL the same and change the part q_\d+,strp to q_100

  • URL with /f/ but no /v1/fill inside: this is the original image, so just download it

  • URL with https://img\d{2} or https://pre\d{2}: this means that the image went through DeviantArt's system and is modified to a specific size. I could not figure out how to get the original image from these types of links, i.e. find https://orig\d{2} from them, so I just download the image as is

@lucas3520
Copy link

It seems it works for posts made before 2019. For posts after 2019, it says something akin to "storage: object does not exist"

But still, a huge thank you for this. It definitely helped with some of my favorite posts there.

@Dishman03
Copy link

This does still work for older images, but has anyone discovered a way to obtain the original res?

@szero
Copy link

szero commented Sep 13, 2024

tested on 2018 image and it worked tho my image had /v1/fit instead of /v1/fill in the url but it still worked

@Orraye
Copy link

Orraye commented Jan 26, 2025

How can I install this onto my mobile device so I can use it?

@MonX23
Copy link

MonX23 commented Aug 19, 2025

time for me to make an example of Intermediary's quality decrease
image
image
for some reason, even though I turned it up to the original resolution, it seems like the image doesn't wanna fully uncompress

@Project-73
Copy link

tested on 2018 image and it worked tho my image had /v1/fit instead of /v1/fill in the url but it still worked

My image has the same /fit but it did not work for me.

https://www.deviantart.com/karosumaker/art/Nadia-1119302871

Modified url: https://images-wixmp-ed30a86b8c4ca887773594c2.wixmp.com/intermediary/f/f681d810-645e-4299-a54c-196da3a50c2e/diiejmf-c6d08c3b-d2c8-4d55-bc60-1d16576390c5.jpg/v1/fill/w_5100,h_5100,bl,q_100/nadia_by_karosumaker_diiejmf-414w-2x.jpg

Please help if you could.

@jka99
Copy link

jka99 commented Aug 29, 2025

tested on 2018 image and it worked tho my image had /v1/fit instead of /v1/fill in the url but it still worked

My image has the same /fit but it did not work for me.

https://www.deviantart.com/karosumaker/art/Nadia-1119302871

Modified url: https://images-wixmp-ed30a86b8c4ca887773594c2.wixmp.com/intermediary/f/f681d810-645e-4299-a54c-196da3a50c2e/diiejmf-c6d08c3b-d2c8-4d55-bc60-1d16576390c5.jpg/v1/fill/w_5100,h_5100,bl,q_100/nadia_by_karosumaker_diiejmf-414w-2x.jpg

Please help if you could.

One thing I noticed is that the above steps don't take into account is the actual size of the image. If you look at the underlying URL, the last piece is the width for a given image. Something like 2560w. That tells you what the numbers after /v1/fill/ should be by calculating the aspect ratio of the image.

Here's a python script i wrote to follow the steps above and calculate the aspect ration, inserting it in the appropriate spot. Seems to work pretty well.

What I do is inspect the image element in DeviantArt with F12 or right click-->Inspect to get the srcset. It will look something like this:

srcset="https://images-wixmp-ed30a86b8c4ca887773594c2.wixmp.com/f/51fd1169-b302-4631-a5c7-04f4fdeaeafd/da6odu8-28221171-66e6-4968-b380-9d86f3fe2fa0.jpg/v1/fit/w_375,h_535,q_70,strp/conan_by_darnet_da6odu8-375w.jpg?token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ1cm46YXBwOjdlMGQxODg5ODIyNjQzNzNhNWYwZDQxNWVhMGQyNmUwIiwiaXNzIjoidXJuOmFwcDo3ZTBkMTg4OTgyMjY0MzczYTVmMGQ0MTVlYTBkMjZlMCIsIm9iaiI6W1t7ImhlaWdodCI6Ijw9MTQ2MCIsInBhdGgiOiJcL2ZcLzUxZmQxMTY5LWIzMDItNDYzMS1hNWM3LTA0ZjRmZGVhZWFmZFwvZGE2b2R1OC0yODIyMTE3MS02NmU2LTQ5NjgtYjM4MC05ZDg2ZjNmZTJmYTAuanBnIiwid2lkdGgiOiI8PTEwMjQifV1dLCJhdWQiOlsidXJuOnNlcnZpY2U6aW1hZ2Uub3BlcmF0aW9ucyJdfQ.oh3OcxAETng9xuVNzBrKTYOj4LR8tGypPqJvuvZQUDM 375w, https://images-wixmp-ed30a86b8c4ca887773594c2.wixmp.com/f/51fd1169-b302-4631-a5c7-04f4fdeaeafd/da6odu8-28221171-66e6-4968-b380-9d86f3fe2fa0.jpg/v1/fit/w_414,h_590,q_70,strp/conan_by_darnet_da6odu8-414w.jpg?token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ1cm46YXBwOjdlMGQxODg5ODIyNjQzNzNhNWYwZDQxNWVhMGQyNmUwIiwiaXNzIjoidXJuOmFwcDo3ZTBkMTg4OTgyMjY0MzczYTVmMGQ0MTVlYTBkMjZlMCIsIm9iaiI6W1t7ImhlaWdodCI6Ijw9MTQ2MCIsInBhdGgiOiJcL2ZcLzUxZmQxMTY5LWIzMDItNDYzMS1hNWM3LTA0ZjRmZGVhZWFmZFwvZGE2b2R1OC0yODIyMTE3MS02NmU2LTQ5NjgtYjM4MC05ZDg2ZjNmZTJmYTAuanBnIiwid2lkdGgiOiI8PTEwMjQifV1dLCJhdWQiOlsidXJuOnNlcnZpY2U6aW1hZ2Uub3BlcmF0aW9ucyJdfQ.oh3OcxAETng9xuVNzBrKTYOj4LR8tGypPqJvuvZQUDM 414w, https://images-wixmp-ed30a86b8c4ca887773594c2.wixmp.com/f/51fd1169-b302-4631-a5c7-04f4fdeaeafd/da6odu8-28221171-66e6-4968-b380-9d86f3fe2fa0.jpg/v1/fill/w_749,h_1068,q_70,strp/conan_by_darnet_da6odu8-pre.jpg?token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ1cm46YXBwOjdlMGQxODg5ODIyNjQzNzNhNWYwZDQxNWVhMGQyNmUwIiwiaXNzIjoidXJuOmFwcDo3ZTBkMTg4OTgyMjY0MzczYTVmMGQ0MTVlYTBkMjZlMCIsIm9iaiI6W1t7ImhlaWdodCI6Ijw9MTQ2MCIsInBhdGgiOiJcL2ZcLzUxZmQxMTY5LWIzMDItNDYzMS1hNWM3LTA0ZjRmZGVhZWFmZFwvZGE2b2R1OC0yODIyMTE3MS02NmU2LTQ5NjgtYjM4MC05ZDg2ZjNmZTJmYTAuanBnIiwid2lkdGgiOiI8PTEwMjQifV1dLCJhdWQiOlsidXJuOnNlcnZpY2U6aW1hZ2Uub3BlcmF0aW9ucyJdfQ.oh3OcxAETng9xuVNzBrKTYOj4LR8tGypPqJvuvZQUDM 749w, https://images-wixmp-ed30a86b8c4ca887773594c2.wixmp.com/f/51fd1169-b302-4631-a5c7-04f4fdeaeafd/da6odu8-28221171-66e6-4968-b380-9d86f3fe2fa0.jpg/v1/fit/w_750,h_1070,q_70,strp/conan_by_darnet_da6odu8-375w-2x.jpg?token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ1cm46YXBwOjdlMGQxODg5ODIyNjQzNzNhNWYwZDQxNWVhMGQyNmUwIiwiaXNzIjoidXJuOmFwcDo3ZTBkMTg4OTgyMjY0MzczYTVmMGQ0MTVlYTBkMjZlMCIsIm9iaiI6W1t7ImhlaWdodCI6Ijw9MTQ2MCIsInBhdGgiOiJcL2ZcLzUxZmQxMTY5LWIzMDItNDYzMS1hNWM3LTA0ZjRmZGVhZWFmZFwvZGE2b2R1OC0yODIyMTE3MS02NmU2LTQ5NjgtYjM4MC05ZDg2ZjNmZTJmYTAuanBnIiwid2lkdGgiOiI8PTEwMjQifV1dLCJhdWQiOlsidXJuOnNlcnZpY2U6aW1hZ2Uub3BlcmF0aW9ucyJdfQ.oh3OcxAETng9xuVNzBrKTYOj4LR8tGypPqJvuvZQUDM 750w, https://images-wixmp-ed30a86b8c4ca887773594c2.wixmp.com/f/51fd1169-b302-4631-a5c7-04f4fdeaeafd/da6odu8-28221171-66e6-4968-b380-9d86f3fe2fa0.jpg/v1/fit/w_828,h_1180,q_70,strp/conan_by_darnet_da6odu8-414w-2x.jpg?token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ1cm46YXBwOjdlMGQxODg5ODIyNjQzNzNhNWYwZDQxNWVhMGQyNmUwIiwiaXNzIjoidXJuOmFwcDo3ZTBkMTg4OTgyMjY0MzczYTVmMGQ0MTVlYTBkMjZlMCIsIm9iaiI6W1t7ImhlaWdodCI6Ijw9MTQ2MCIsInBhdGgiOiJcL2ZcLzUxZmQxMTY5LWIzMDItNDYzMS1hNWM3LTA0ZjRmZGVhZWFmZFwvZGE2b2R1OC0yODIyMTE3MS02NmU2LTQ5NjgtYjM4MC05ZDg2ZjNmZTJmYTAuanBnIiwid2lkdGgiOiI8PTEwMjQifV1dLCJhdWQiOlsidXJuOnNlcnZpY2U6aW1hZ2Uub3BlcmF0aW9ucyJdfQ.oh3OcxAETng9xuVNzBrKTYOj4LR8tGypPqJvuvZQUDM 2048w"

From there, I find the URL that has the size I'm looking for. Let's say it's this:

https://images-wixmp-ed30a86b8c4ca887773594c2.wixmp.com/f/51fd1169-b302-4631-a5c7-04f4fdeaeafd/da6odu8-28221171-66e6-4968-b380-9d86f3fe2fa0.jpg/v1/fit/w_828,h_1180,q_70,strp/conan_by_darnet_da6odu8-414w-2x.jpg?token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ1cm46YXBwOjdlMGQxODg5ODIyNjQzNzNhNWYwZDQxNWVhMGQyNmUwIiwiaXNzIjoidXJuOmFwcDo3ZTBkMTg4OTgyMjY0MzczYTVmMGQ0MTVlYTBkMjZlMCIsIm9iaiI6W1t7ImhlaWdodCI6Ijw9MTQ2MCIsInBhdGgiOiJcL2ZcLzUxZmQxMTY5LWIzMDItNDYzMS1hNWM3LTA0ZjRmZGVhZWFmZFwvZGE2b2R1OC0yODIyMTE3MS02NmU2LTQ5NjgtYjM4MC05ZDg2ZjNmZTJmYTAuanBnIiwid2lkdGgiOiI8PTEwMjQifV1dLCJhdWQiOlsidXJuOnNlcnZpY2U6aW1hZ2Uub3BlcmF0aW9ucyJdfQ.oh3OcxAETng9xuVNzBrKTYOj4LR8tGypPqJvuvZQUDM 2048w

I paste that into the script and out comes the cleaned URL to the large image, like this:

https://images-wixmp-ed30a86b8c4ca887773594c2.wixmp.com/intermediary/f/f681d810-645e-4299-a54c-196da3a50c2e/diiejmf-c6d08c3b-d2c8-4d55-bc60-1d16576390c5.jpg/v1/fill/w_2560,h_3821,q_70/nadia_by_karosumaker_diiejmf-414w-2x.jpg

Unfortunately, I couldn't get it to work for the above example. Maybe it'll work on a different image?

import re

# Paste your URL here
url = ""

print("Starting script...")

if url:
    print("URL found!")
    # Remove token
    base_url = url.split('?token=')[0]
    
    # Add intermediary
    base_url = base_url.replace('/f/', '/intermediary/f/')
    
    # Get max width from end
    max_width_match = re.search(r'(\d+)w\s*$', url)
    max_width = int(max_width_match.group(1)) if max_width_match else 2048
    
    # Get current dimensions
    fill_match = re.search(r'/v1/(fill|fit)/([^/]+)/', base_url)
    if fill_match:
        params = fill_match.group(2)
        width_match = re.search(r'w_(\d+)', params)
        height_match = re.search(r'h_(\d+)', params)
        quality_match = re.search(r'q_(\d+)', params)
        
        if width_match and height_match:
            w = int(width_match.group(1))
            h = int(height_match.group(1))
            q = quality_match.group(1) if quality_match else '70'
            
            new_h = int((h/w) * max_width)
            new_params = f"w_{max_width},h_{new_h},q_{q}"
            
            cleaned = re.sub(r'/v1/(fill|fit)/[^/]+/', f'/v1/fill/{new_params}/', base_url)
            
            print("Original:")
            print(url)
            print("\nCleaned:")
            print(cleaned)
        else:
            print("Could not parse dimensions")
    else:
        print("No fill/fit found")
else:
    print("No URL found - paste it in the url variable")

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment