Size
8.4 KB
Version
1.0.1
Created
Dec 2, 2025
Updated
15 days ago
1// ==UserScript==
2// @name Article Login & Paywall Bypass
3// @description Automatically bypass login walls and paywalls on articles
4// @version 1.0.1
5// @match *://*/*
6// ==/UserScript==
7(function() {
8 'use strict';
9
10 console.log('Article Login & Paywall Bypass extension loaded');
11
12 // Debounce function to prevent excessive calls
13 function debounce(func, wait) {
14 let timeout;
15 return function executedFunction(...args) {
16 const later = () => {
17 clearTimeout(timeout);
18 func(...args);
19 };
20 clearTimeout(timeout);
21 timeout = setTimeout(later, wait);
22 };
23 }
24
25 // Remove overlay elements that block content
26 function removeOverlays() {
27 console.log('Removing overlay elements...');
28
29 // Common overlay selectors
30 const overlaySelectors = [
31 '[class*="paywall"]',
32 '[id*="paywall"]',
33 '[class*="overlay"]',
34 '[id*="overlay"]',
35 '[class*="modal"]',
36 '[id*="modal"]',
37 '[class*="popup"]',
38 '[id*="popup"]',
39 '[class*="login-wall"]',
40 '[id*="login-wall"]',
41 '[class*="subscription"]',
42 '[id*="subscription"]',
43 '[class*="premium"]',
44 '[id*="premium"]',
45 '[class*="gate"]',
46 '[id*="gate"]',
47 '[class*="barrier"]',
48 '[id*="barrier"]'
49 ];
50
51 overlaySelectors.forEach(selector => {
52 const elements = document.querySelectorAll(selector);
53 elements.forEach(el => {
54 // Check if element is likely an overlay (fixed/absolute positioning)
55 const style = window.getComputedStyle(el);
56 if (style.position === 'fixed' || style.position === 'absolute') {
57 console.log('Removing overlay element:', el);
58 el.remove();
59 }
60 });
61 });
62 }
63
64 // Remove blur effects from content
65 function removeBlur() {
66 console.log('Removing blur effects...');
67
68 const allElements = document.querySelectorAll('*');
69 allElements.forEach(el => {
70 const style = window.getComputedStyle(el);
71 if (style.filter && style.filter.includes('blur')) {
72 console.log('Removing blur from element:', el);
73 el.style.filter = 'none';
74 el.style.webkitFilter = 'none';
75 }
76 });
77 }
78
79 // Restore scroll functionality
80 function restoreScroll() {
81 console.log('Restoring scroll functionality...');
82
83 // Remove overflow hidden from body and html
84 document.body.style.overflow = 'auto';
85 document.body.style.overflowY = 'auto';
86 document.documentElement.style.overflow = 'auto';
87 document.documentElement.style.overflowY = 'auto';
88
89 // Remove position fixed from body
90 document.body.style.position = 'static';
91
92 // Remove height restrictions
93 document.body.style.height = 'auto';
94 document.documentElement.style.height = 'auto';
95 }
96
97 // Expand truncated content
98 function expandContent() {
99 console.log('Expanding truncated content...');
100
101 // Look for elements with max-height restrictions
102 const allElements = document.querySelectorAll('article, [class*="content"], [class*="article"], [id*="content"], [id*="article"]');
103 allElements.forEach(el => {
104 const style = window.getComputedStyle(el);
105 if (style.maxHeight && style.maxHeight !== 'none') {
106 console.log('Expanding content element:', el);
107 el.style.maxHeight = 'none';
108 el.style.height = 'auto';
109 }
110 if (style.overflow === 'hidden') {
111 el.style.overflow = 'visible';
112 }
113 });
114
115 // Remove gradient overlays that hide content
116 const gradients = document.querySelectorAll('[class*="gradient"], [class*="fade"]');
117 gradients.forEach(el => {
118 const style = window.getComputedStyle(el);
119 if (style.background && (style.background.includes('gradient') || style.background.includes('linear'))) {
120 console.log('Removing gradient overlay:', el);
121 el.remove();
122 }
123 });
124 }
125
126 // Remove CSS that hides content
127 function removeCSSRestrictions() {
128 console.log('Removing CSS restrictions...');
129
130 // Add custom CSS to override common paywall styles
131 const css = `
132 body, html {
133 overflow: auto !important;
134 overflow-y: auto !important;
135 position: static !important;
136 height: auto !important;
137 }
138 [class*="paywall"],
139 [id*="paywall"],
140 [class*="login-wall"],
141 [id*="login-wall"],
142 [class*="subscription-wall"],
143 [id*="subscription-wall"] {
144 display: none !important;
145 visibility: hidden !important;
146 }
147 article,
148 [class*="article"],
149 [class*="content"],
150 [id*="article"],
151 [id*="content"] {
152 max-height: none !important;
153 height: auto !important;
154 overflow: visible !important;
155 filter: none !important;
156 -webkit-filter: none !important;
157 }
158 `;
159
160 TM_addStyle(css);
161 }
162
163 // Remove event listeners that prevent interaction
164 function removeEventListeners() {
165 console.log('Removing restrictive event listeners...');
166
167 // Remove click blockers
168 document.body.style.pointerEvents = 'auto';
169
170 // Re-enable right-click
171 document.addEventListener('contextmenu', function(e) {
172 e.stopPropagation();
173 }, true);
174
175 // Re-enable text selection
176 document.body.style.userSelect = 'auto';
177 document.body.style.webkitUserSelect = 'auto';
178 }
179
180 // Check for and remove specific paywall implementations
181 function removeSpecificPaywalls() {
182 console.log('Checking for specific paywall implementations...');
183
184 // Medium paywall
185 if (window.location.hostname.includes('medium.com')) {
186 const paywallDiv = document.querySelector('[data-testid="paywall"]');
187 if (paywallDiv) paywallDiv.remove();
188 }
189
190 // New York Times
191 if (window.location.hostname.includes('nytimes.com')) {
192 const gateway = document.querySelector('[id*="gateway"]');
193 if (gateway) gateway.remove();
194 }
195
196 // Wall Street Journal
197 if (window.location.hostname.includes('wsj.com')) {
198 const snippet = document.querySelector('[class*="snippet"]');
199 if (snippet) snippet.style.maxHeight = 'none';
200 }
201
202 // Bloomberg
203 if (window.location.hostname.includes('bloomberg.com')) {
204 const fence = document.querySelector('[class*="fence"]');
205 if (fence) fence.remove();
206 }
207 }
208
209 // Main bypass function
210 function bypassLoginWall() {
211 console.log('Running login wall bypass...');
212
213 removeOverlays();
214 removeBlur();
215 restoreScroll();
216 expandContent();
217 removeCSSRestrictions();
218 removeEventListeners();
219 removeSpecificPaywalls();
220
221 console.log('Login wall bypass complete');
222 }
223
224 // Initialize the extension
225 function init() {
226 console.log('Initializing Article Login & Paywall Bypass...');
227
228 // Run immediately
229 bypassLoginWall();
230
231 // Run after a short delay to catch dynamically loaded paywalls
232 setTimeout(bypassLoginWall, 2000);
233 setTimeout(bypassLoginWall, 5000);
234
235 // Watch for DOM changes and re-run bypass
236 const debouncedBypass = debounce(bypassLoginWall, 1000);
237 const observer = new MutationObserver(debouncedBypass);
238
239 observer.observe(document.body, {
240 childList: true,
241 subtree: true,
242 attributes: true,
243 attributeFilter: ['class', 'style']
244 });
245
246 console.log('Article Login & Paywall Bypass initialized successfully');
247 }
248
249 // Wait for body to be ready
250 if (document.body) {
251 init();
252 } else {
253 TM_runBody(init);
254 }
255
256})();