Skip to content

Instantly share code, notes, and snippets.

@christophemarois
Last active February 15, 2024 11:32
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save christophemarois/fa4e023419dda613fde03cbb610df83f to your computer and use it in GitHub Desktop.
Save christophemarois/fa4e023419dda613fde03cbb610df83f to your computer and use it in GitHub Desktop.
Demonstrate how to replace images with their base64 equivalent regardless of same-origin policy using GM_xmlhttpRequest. Still requires permission from Tampermonkey.
// ==UserScript==
// @name Base64 inline images
// @author @christophemarois
// @match *
// @grant GM_xmlhttpRequest
// @connect *
// ==/UserScript==
// NOTE: NOT MEANT TO BE INSTALLED
// AS IT WILL REPLACE EVERY IMAGE ON EVERY PAGE
// INFORMATIVE PURPOSES ONLY
(function() {
const inlineBase64Images = nodes => {
let imgs = Array.from(nodes).filter(node => node.matches('img'))
return Promise.all(imgs.map(img => new Promise(res => {
GM_xmlhttpRequest({
method: 'GET',
url: img.src,
responseType: 'blob',
onload: function(xhr) {
if (xhr.status !== 200) return res(null)
let headers = {}
for (let header of xhr.responseHeaders.trim().split(/\n/)) {
let parts = header.split(':')
if (parts.length === 1) continue
headers[parts[0].trim()] = parts[1].trim()
}
let type = headers['Content-Type']
if (!/^image\//.test(type)) {
if (/\.jpe?g$/i.test(img.src)) type = 'image/jpeg'
if (/\.png$/i.test(img.src)) type = 'image/png'
if (/\.gif$/i.test(img.src)) type = 'image/png'
}
if (!/^image\//.test(type)) {
console.error(`Can't process "${img.src}" because its type is "${type}"`)
return res(null)
}
let imgEl = new Image()
imgEl.onload = function () {
let canvas = document.createElement('canvas');
canvas.width = imgEl.naturalWidth;
canvas.height = imgEl.naturalHeight;
try {
canvas.getContext('2d').drawImage(imgEl, 0, 0)
img.src = canvas.toDataURL(type, 0.7)
res(img)
} catch (e) {
console.error(`Can't draw "${img.src}" on a canvas`, e)
res(null)
}
}
imgEl.onerror = () => res(null)
imgEl.src = window.URL.createObjectURL(xhr.response)
}
})
})))
// At this point, imgs is an array of all the <img> tags of the page
// who had their content base64'd. Some elements might be null if
// XHR or canvas conversion failed on them. Filter them out.
.then(imgs => Promise.resolve(imgs.filter(img => !!img)))
}
let startTime = +new Date
inlineBase64Images(document.querySelectorAll('img')).then(imgs => {
console.log(imgs.length + ' images converted in ' + ((+new Date) - startTime) / 1000 + 's')
})
})()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment