NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript==
// @name Medium Unlocker
// @namespace https://openuserjs.org/users/medium-unlocker
// @version 25.08.06
// @description Adds a button to Medium articles to bypass the paywall by opening them in Freedium or ReadMedium.
// @author asurpbs
// @license MIT
// @homepageURL https://openuserjs.org/scripts/asurpbs/Medium_Unlocker
// @supportURL https://openuserjs.org/scripts/asurpbs/Medium_Unlocker/issues
// @icon data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0iI2ZmZmZmZiIgd2lkdGg9IjY0cHgiIGhlaWdodD0iNjRweCI+PHBhdGggZD0iTTIgMmgxMHYySDJ6bTAgNWg4djJIMHptMCA1aDEwdjJIMHptMCA1aDh2Mkgyem0xMy43MSAxLjI5bC00LTQgMS40Mi0xLjQyIDQuMjkgNC4yOS0xLjQxIDEuNDF6bS0xLjQxIDUuNzFMMTAgMTQuNDJsMS40MS0xLjQxIDQuMjkgNC4yOS0xLjQxIDEuNDF6Ii8+PC9zdmc+
// @match https://medium.com/*/*
// @match https://*.medium.com/*
// @grant GM_addStyle
// @updateURL https://openuserjs.org/meta/asurpbs/Medium_Unlocker.meta.js
// @downloadURL https://openuserjs.org/install/asurpbs/Medium_Unlocker.user.js
// @copyright 2025, asurpbs (https://openuserjs.org/users/asurpbs)
// @license MIT
// @run-at document-end
// ==/UserScript==
(function () {
'use strict';
GM_addStyle(`
:root {
--fluent-blue: #0078D4;
--fluent-blue-hover: #005A9E;
--fluent-background: rgba(255, 255, 255, 0.9);
--fluent-border-radius: 8px;
--fluent-shadow: 0 6px 12px rgba(0,0,0,0.15), 0 2px 4px rgba(0,0,0,0.1);
--fluent-text-dark: #212121;
--fluent-text-light: #FFFFFF;
}
#medium-unlock-button {
position: fixed;
bottom: 20px;
right: 20px;
z-index: 9999;
background-color: var(--fluent-blue);
color: var(--fluent-text-light);
border: none;
border-radius: 50px;
padding: 12px 20px;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
font-size: 16px;
font-weight: 600;
cursor: pointer;
box-shadow: var(--fluent-shadow);
display: flex;
align-items: center;
gap: 8px;
transition: background-color 0.2s ease, transform 0.2s ease;
}
#medium-unlock-button:hover {
background-color: var(--fluent-blue-hover);
transform: translateY(-2px);
}
#unlock-modal-backdrop {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.4);
z-index: 10000;
display: none;
justify-content: center;
align-items: center;
backdrop-filter: blur(5px);
-webkit-backdrop-filter: blur(5px);
}
#unlock-modal-container {
background-color: var(--fluent-background);
padding: 28px;
border-radius: var(--fluent-border-radius);
box-shadow: var(--fluent-shadow);
width: 90%;
max-width: 400px;
text-align: center;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
animation: fadeIn 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94);
border: 1px solid rgba(0, 0, 0, 0.1);
}
@keyframes fadeIn {
from { opacity: 0; transform: translateY(10px) scale(0.98); }
to { opacity: 1; transform: translateY(0) scale(1); }
}
#unlock-modal-container h2 {
margin-top: 0;
margin-bottom: 16px;
color: var(--fluent-text-dark);
font-size: 22px;
font-weight: 600;
}
#unlock-modal-container p {
margin-bottom: 24px;
color: #555;
font-size: 16px;
line-height: 1.5;
}
.unlock-options {
display: flex;
flex-direction: column;
gap: 12px;
}
.unlock-option-button {
background-color: rgba(0, 0, 0, 0.05);
color: var(--fluent-text-dark);
border: 1px solid rgba(0, 0, 0, 0.1);
padding: 14px;
border-radius: var(--fluent-border-radius);
font-size: 16px;
font-weight: 500;
cursor: pointer;
transition: background-color 0.2s ease, border-color 0.2s ease;
width: 100%;
}
.unlock-option-button:hover {
background-color: rgba(0, 0, 0, 0.1);
border-color: rgba(0, 0, 0, 0.15);
}
.unlock-option-button.primary {
background-color: var(--fluent-blue);
color: var(--fluent-text-light);
border: none;
}
.unlock-option-button.primary:hover {
background-color: var(--fluent-blue-hover);
}
`);
const unlockButton = document.createElement('button');
unlockButton.id = 'medium-unlock-button';
unlockButton.innerHTML = `
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">
<rect x="3" y="11" width="18" height="11" rx="2" ry="2"></rect>
<path d="M7 11V7a5 5 0 0 1 10 0v4"></path>
</svg>
<span>Unlock</span>
`;
const modalBackdrop = document.createElement('div');
modalBackdrop.id = 'unlock-modal-backdrop';
const modalContainer = document.createElement('div');
modalContainer.id = 'unlock-modal-container';
modalContainer.innerHTML = `
<h2>Read without limits</h2>
<p>Choose a service to open this article and bypass the paywall.</p>
<div class="unlock-options">
<button id="freedium-btn" class="unlock-option-button primary">Read on Freedium</button>
<button id="readmedium-btn" class="unlock-option-button">Read on ReadMedium</button>
</div>
`;
modalBackdrop.appendChild(modalContainer);
document.body.appendChild(unlockButton);
document.body.appendChild(modalBackdrop);
const freediumBtn = document.getElementById('freedium-btn');
const readMediumBtn = document.getElementById('readmedium-btn');
const toggleModal = (show) => {
modalBackdrop.style.display = show ? 'flex' : 'none';
};
unlockButton.addEventListener('click', () => toggleModal(true));
modalBackdrop.addEventListener('click', (e) => {
if (e.target === modalBackdrop) {
toggleModal(false);
}
});
freediumBtn.addEventListener('click', () => {
const currentUrl = window.location.href;
const freediumUrl = `https://freedium.cfd/${currentUrl}`;
window.location.href = freediumUrl;
});
readMediumBtn.addEventListener('click', () => {
const currentUrl = window.location.href;
const slug = currentUrl.split('?')[0].split('/').pop();
if (slug) {
const readMediumUrl = `https://readmedium.com/en/${slug}`;
window.location.href = readMediumUrl;
}
else {
toggleModal(false);
}
});
})();