Last active
July 20, 2024 08:32
-
-
Save fanfare/1305eb8698021434768bed0ab4883d7b to your computer and use it in GitHub Desktop.
get google related images URL ( https://www.google.com/search?tbs=sbi: ... ) based on an image URL
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// notes: | |
// this function should be used from within the background script of a webextension | |
// also included are two examples at the bottom to demonstrate its use | |
async function getImageResultsURLFromImageURL(URL) { | |
// input: string | |
// the input is the URL of the image you want to search for | |
// it can either start with "http" or "data:" (for base64 encoded images) | |
// output: string | |
// the output is the URL of the image results (regular, not google lens) | |
// the output URL starts with "https://www.google.com/search?tbs=sbi:" | |
const lens = async (URL) => { | |
// find the normal image results URL within the HTML of the Google Lens results | |
const response = await fetch(URL, { | |
"body": null, | |
"method": "GET", | |
"mode": "cors", | |
}) | |
let body = await response.text() | |
let index = body.indexOf(`https://www.google.com/search?tbs`) | |
if (index === -1) { | |
throw new Error("tbs prefix url not found") | |
} | |
body = body.substring(index, body.length) | |
index = body.indexOf(`"`) | |
if (index === -1) { | |
throw new Error("quotation marks not found") | |
} | |
body = body.substring(0,index) | |
body = body.replace(`\\u003d`, "=") | |
if (!body.startsWith("https")) { | |
throw new Error(`body does not start with https, body length is ${body.length}`) | |
} | |
return body | |
} | |
const get = async (URL) => { | |
// find the Google Lens results URL from an HTTP/HTTPS image URL | |
const encodedURL = encodeURIComponent(URL) | |
const crawlRequestURL = `https://lens.google.com/uploadbyurl?url=${encodedURL}&hl=en&re=df&st=${+ new Date()}&ep=gisbubu` | |
const response = await fetch(crawlRequestURL, { | |
"body": null, | |
"method": "GET", | |
"mode": "cors", | |
}) | |
return response.url | |
} | |
const post = async (URL) => { | |
// find the Google Lens results URL from a base64 image URL | |
const blob = await (await fetch(URL)).blob() | |
const formData = new FormData() | |
formData.append("encoded_image", blob, `${+ new Date()}.png`) | |
let response = await fetch(`https://lens.google.com/upload?hl=en&re=df&st=${+ new Date()}&ep=gisbubb`, { | |
"body": formData, | |
"method": "POST", | |
"mode": "cors" | |
}) | |
let text = await response.text() | |
if (text.indexOf("refresh") === -1) { | |
throw new Error("no base64 meta refresh found") | |
return null | |
} | |
let index = text.indexOf('https://lens.google.com') | |
text = text.slice(index) | |
index = text.indexOf('"') | |
if (index === -1) { | |
index = text.indexOf("'") | |
if (index === -1) { | |
throw new Error("quotation marks not found") | |
return null | |
} | |
} | |
text = text.slice(0,index) | |
if (!text.startsWith("http")) { | |
throw new Error("url did not start with http") | |
return null | |
} | |
return text | |
} | |
try { | |
// if no valid URL provided, return null | |
if (!URL || URL.length === 0 || typeof URL !== "string") { | |
return null | |
} | |
let redirect = null | |
if (URL.startsWith("data:")) { | |
// get the Google Lens URL based on a base64 image URL | |
redirect = await post(URL) | |
} | |
else { | |
// get the Google Lens URL based on an HTTP/HTTPS image URL | |
redirect = await get(URL) | |
} | |
// return the normal image results URL | |
return await lens(redirect) | |
} | |
catch(e) { | |
console.error(e) | |
if (!URL.startsWith("data:")) { | |
// as a fallback, return the Google Lens results URL | |
const encodedURL = URL.replaceAll("?", '%3F').replaceAll("&", '%26') | |
return `https://lens.google.com/uploadbyurl?url=${encodedURL}` | |
} | |
else { | |
// return null if a base64 image was provided and wasn't able to resolve | |
return null | |
} | |
} | |
}; | |
// examples: | |
// get the normal image results URL from an HTTPS image URL | |
(async function() { | |
const imageURL = "https://i.imgur.com/VcMUWBC.jpeg" | |
const results = await getImageResultsURLFromImageURL(imageURL) | |
console.log(results) // https://www.google.com/search?tbs=sbi:AMhZZisKeirUN5_1-_1AfP0ZUcMShmlwPs0MGTCsOcPrfqv_1ii1AY2ximpsNpO6TnEsNDa8L5Bc0hKxRecsm8wEJfgFG1K85SBAGW-K3bb0sVPuImQHW24qIIU7xfzRpHFgKl2REAScR2RGphYZDWf_1dBxVNefRmZ2GQ | |
})(); | |
// get the normal image results URL from a base64 image URL | |
(async function() { | |
const imageURL = "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAkGBwgHBgkIBwgKCgkLDRYPDQwMDRsUFRAWIB0iIiAdHx8kKDQsJCYxJx8fLT0tMTU3Ojo6Iys/RD84QzQ5Ojf/2wBDAQoKCg0MDRoPDxo3JR8lNzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzf/wAARCAA3AEADASIAAhEBAxEB/8QAGwAAAQUBAQAAAAAAAAAAAAAAAwABAgQGBQf/xAAuEAABAwMDAwMDAwUAAAAAAAABAgMRAAQhBRIxBkFRE2GRInGBBxUjQrHBwvH/xAAUAQEAAAAAAAAAAAAAAAAAAAAA/8QAFBEBAAAAAAAAAAAAAAAAAAAAAP/aAAwDAQACEQMRAD8A3u2BkVBSRNHXxxQinufigGpM8CkEfaalkU6YJoIhvBEjzVttsgZpkISck0YEJQIoGSIoVyqBTrUQJFVHVFVBegETzQHOTIqCn9oMngE1Ru9XtrZj1XlFKZAHuT2oLiqGCArmq5v2yQPUSCUBwJnO08Ggm9QraUuJIVxnmg6gdAwap6zqZ0/S7i7QkKLQBgmJyB/mgrW4kwsKB8RWX/US6eY6aWlKlILr6EScEQd3+poNJpeuo1AlsgpdCd57CCTA+Iq+pxPIIzXkXSXUbyNfs7Iytl1JSpRA/jMKxMeYrR9U9WuaS+1b2RaW5G971ASAOwwee/x5oCtalqPqKW9cBSFgBaV7SFQIyAnv3oGqajYXG4XTyUoUZLTaglM+Y5rzA3jzuXHHHPdajFSFyEwScc/SIn80G/vepkOLQbZl10oSEhSzCIE/MzmuVc9UagXVlHopMlZVtnNZNd6oz/SIzmhquCRHCfPn8UGuV1rrjLywm5acTG36mhH3Heff2rja71JfaslAvblBbQorS2luADBAgknyfmuM/cGRCjCgJk81VU7uOc0He03qH9ouGLmwU2l1pxKzKNwVBGCPBgfFB1zX3db1S71G4DaXrggrDSNqcJCRjMYArjExGMeB3qTTqmd3p7khRE/VzH/aBw4R3n3PYU3qc5JHmaVKgip2B/ao7lFEnv3pUqBE7m442nAqA7mceaVKgtIKQjByJ4FV1ncQASSPNKlQf//Z" | |
const results = await getImageResultsURLFromImageURL(imageURL) | |
console.log(results) // https://www.google.com/search?tbs=sbi:AMhZZiuQRfow5gK0DKoShC5tjLNXDbIsFPMtCfNpUGU2NtsYLLbRE16ITRsECSMmZC8I1HmU04Cgi0--0qUci_14tkoOZAg2gisCcAOceGfFNypdlC0W5SP9hhW7qwbq-OSkd-ts49B6k5KLXfFZTC5KOsrBJiRs3HA | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment