Greasy Fork is available in English.

Twitter/X Nitter Redirect

Redirect twitter.com and x.com links to a random healthy Nitter instance.

  1. // ==UserScript==
  2. // @name Twitter/X Nitter Redirect
  3. // @version 1.0
  4. // @description Redirect twitter.com and x.com links to a random healthy Nitter instance.
  5. // @author yodaluca23
  6. // @license GNU GPLv3
  7. // @match *://twitter.com/*
  8. // @match *://www.twitter.com/*
  9. // @match *://x.com/*
  10. // @match *://www.x.com/*
  11. // @grant GM_xmlhttpRequest
  12. // @namespace http://tampermonkey.net/
  13. // ==/UserScript==
  14.  
  15. (function() {
  16. 'use strict';
  17.  
  18. const staticURL = ''; // Set this to an instance if you always want to use a single Nitter instance instead of fetching from API.
  19.  
  20. const apiUrl = 'https://status.d420.de/api/v1/instances';
  21.  
  22. const profileURLPattern = /^https?:\/\/(www\.)?(twitter\.com|x\.com)\/[A-Za-z0-9_]+(\/.*)?$/;
  23.  
  24. let currentURL = window.location.href;
  25.  
  26. function fetchNitterInstance(callback) {
  27. GM_xmlhttpRequest({
  28. method: 'GET',
  29. url: apiUrl,
  30. onload: function(response) {
  31. try {
  32. const data = JSON.parse(response.responseText);
  33.  
  34. if (!data.hosts || !Array.isArray(data.hosts)) {
  35. console.error('Unexpected API response format:', data);
  36. return;
  37. }
  38.  
  39. const healthyInstances = data.hosts.filter(host => host.healthy && !host.is_bad_host);
  40.  
  41. if (healthyInstances.length > 0) {
  42. const randomInstance = healthyInstances[Math.floor(Math.random() * healthyInstances.length)];
  43. callback(randomInstance.domain);
  44. } else {
  45. console.warn('No healthy Nitter instances found.');
  46. }
  47. } catch (error) {
  48. console.error('Failed to parse Nitter instance data:', error, response.responseText);
  49. }
  50. },
  51. onerror: function(error) {
  52. console.error('Error fetching Nitter instances:', error);
  53. }
  54. });
  55. }
  56.  
  57. function redirectToNitter(nitterDomain) {
  58. if (profileURLPattern.test(currentURL)) {
  59. let newURL = currentURL.replace(/(twitter\.com|x\.com)/, nitterDomain);
  60. console.log('Redirecting to:', newURL);
  61. if (newURL !== currentURL) {
  62. window.location.replace(newURL);
  63. }
  64. } else {
  65. console.log('URL does not match profile pattern, no redirection.');
  66. }
  67. }
  68. if (staticURL.length > 1) {
  69. redirectToNitter(staticURL);
  70. } else {
  71. fetchNitterInstance(redirectToNitter);
  72. }
  73. })();