Greasy Fork is available in English.
Adds a percentage of incorrectness to your GeoGuessr guesses. For example, if set to 10%, and your guess would have been 10km away, your guess will be moved 11km away.
// ==UserScript== // @name Guess Incorrector // @description Adds a percentage of incorrectness to your GeoGuessr guesses. For example, if set to 10%, and your guess would have been 10km away, your guess will be moved 11km away. // @license MIT // @namespace http://tampermonkey.net/ // @version 2026-03-12 // @match *://*.geoguessr.com/* // @run-at document-start // @grant unsafeWindow // @grant GM_registerMenuCommand // @require https://cdn.jsdelivr.net/npm/[email protected]/lib/index.js // ==/UserScript== let percentage = parseInt( localStorage.getItem( 'incorrectorpercentage' ), 10 ) || 0; let gcoords = [ 0, 0 ]; const showOptions = () => { let optionsWindow = document.querySelector('#incorrectorOptions'); if ( ! optionsWindow ) { optionsWindow = document.createElement( 'div' ); optionsWindow.id = 'incorrectorOptions'; optionsWindow.style.borderRadius = '16px'; optionsWindow.style.textAlign = 'center'; optionsWindow.style.padding = '14px'; optionsWindow.style.position = 'absolute'; optionsWindow.style.width = '600px'; optionsWindow.style.zIndex = '999999'; optionsWindow.style.top = '20%'; optionsWindow.style.left = 'calc( 50vw - 300px )'; optionsWindow.style.backgroundColor = 'rgba(255,255,255,.94)'; const h1 = document.createElement( 'h1' ); h1.innerText = 'Guess Incorrector Settings'; const h2 = document.createElement( 'h2' ); h2.innerText = `Add ${ percentage }% incorrectness`; const h3 = document.createElement( 'h3' ); h3.innerText = `A guess that is 100km away would change to ${ Math.round( 100 * ( 1 + percentage / 100 ) ) }km away`; h3.style.marginBottom = '22px'; const pInput = document.createElement( 'input' ); pInput.type='range'; pInput.min='0'; pInput.max='180'; pInput.step='1'; pInput.value=percentage <= 100 ? percentage : 100 + ( percentage - 100 ) / 10; const update = () => { const value = parseInt( pInput.value, 10 ) percentage = value <= 100 ? value : 100 + ( value - 100 ) * 10; h2.innerText = `Add ${ percentage }% incorrectness`; h3.innerText = `A guess that is 100km away would change to ${ Math.round( 100 * ( 1 + percentage / 100 ) ) }km away`; localStorage.setItem( 'incorrectorpercentage', percentage ); }; pInput.oninput = update; pInput.onchange = update; const close = document.createElement( 'button' ); close.innerText = 'Close Settings'; close.onclick = () => optionsWindow.style.display = 'none'; close.style.margin='12px'; close.style.padding='8px'; close.style.borderRadius='6px'; close.style.width='60%'; close.style.backgroundColor='#23c921'; const note = document.createElement( 'div' ); note.innerText = "If you've already placed a marker, setting won't take effect until next marker placement."; note.style.fontSize = '0.85em'; note.style.color = '#777'; optionsWindow.appendChild( h1 ); optionsWindow.appendChild( h2 ); optionsWindow.appendChild( pInput ); optionsWindow.appendChild( h3 ); optionsWindow.appendChild( close ); optionsWindow.appendChild( note ); document.body.appendChild( optionsWindow ); optionsWindow.style.display = 'block'; } else if ( optionsWindow.style.display === 'block' ){ optionsWindow.style.display = 'none'; } else { optionsWindow.style.display = 'block'; } }; GM_registerMenuCommand( "Configure", showOptions ); function calculateIncorrectedLatLong( latitude, longitude ) { const distance = window.geolib.getPreciseDistance( { latitude: gcoords[0], longitude: gcoords[1] }, { latitude, longitude } ); const bearing = window.geolib.getGreatCircleBearing( { latitude: gcoords[0], longitude: gcoords[1] }, { latitude, longitude } ); const incorrected = window.geolib.computeDestinationPoint( { latitude: gcoords[0], longitude: gcoords[1] }, // 20000000 meters is roughly half the earth's circumference // If we move further than that, we actually may be making the guess closer Math.min( distance * ( 1 + percentage / 100 ), 20000000 ), bearing ); return incorrected; } const originalFetch = unsafeWindow.fetch; const updateButton = () => { const button = document.querySelector('button[data-qa=perform-guess]'); if ( ! button || button.disabled ) return; button.style.background = percentage > 0 ? '#cb0561' : ''; button.innerText = percentage > 0 ? `GUESS (+${percentage}% incorrect)` : 'GUESS'; }; setInterval( updateButton, 250 ); unsafeWindow.fetch = new Proxy( originalFetch, { apply: function (target, that, args) { let [resource, config] = args; if ( percentage > 0 ) { if ( resource.match && ( resource?.match( /^https:\/\/www\.geoguessr\.com\/api\/v\d\/games\// ) || resource?.match( /^https:\/\/[^\.]+\.geoguessr\.com\/.*?\/(guess|pin)$/ ) ) ) { if ( config?.body ) { const orig = JSON.parse( config.body ); if ( orig.lat && orig.lng ) { const incorrected = calculateIncorrectedLatLong( orig.lat, orig.lng ); if ( incorrected.latitude && incorrected.longitude ) { config.body = JSON.stringify( { ...orig, lat: incorrected.latitude, lng: incorrected.longitude, } ); } } } } } const promise = Reflect.apply(target, that, args); return promise; } } ); const originalOpen = XMLHttpRequest.prototype.open; XMLHttpRequest.prototype.open = function(method, url) { if (method.toUpperCase() === 'POST' && (url.startsWith('https://maps.googleapis.com/$rpc/google.internal.maps.mapsjs.v1.MapsJsInternalService/GetMetadata') || url.startsWith('https://maps.googleapis.com/$rpc/google.internal.maps.mapsjs.v1.MapsJsInternalService/SingleImageSearch'))) { this.addEventListener('load', function () { const pattern = /-?\d+\.\d+,-?\d+\.\d+/g; const match = this.responseText.match(pattern); if (match && match[0]) { const [lat, lng] = match[0].split(",").map(Number); gcoords = [ lat, lng ]; } }); } return originalOpen.apply(this, arguments); };