Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
662ae90
Bypass Cloudflare 403 error using cloudscraper (#1291)
0xbarchitect Oct 12, 2025
32b04a7
Include pinned tweets in RSS
zedeus Nov 15, 2025
9e95615
Remove unused skipPinned parameter
zedeus Nov 15, 2025
f89d232
Add cookie-based authentication support
zedeus Nov 15, 2025
3768762
Add script for generating cookies
zedeus Nov 16, 2025
6fe850b
Add optional cookie session fields
zedeus Nov 16, 2025
4fc7b87
Use dynamic rate limits from API responses
zedeus Nov 16, 2025
5aa0b65
Add bearer token for cookie-based auth
zedeus Nov 16, 2025
bf36fc4
Update tests
zedeus Nov 16, 2025
55d4469
fix: correct argument parsing for --append flag in get_web_session.py…
0xcathiefish Nov 16, 2025
68fc7b7
Fix media support for cookie sessions
zedeus Nov 16, 2025
3f3196d
Fix broken UserMedia photo rail parsing
zedeus Nov 16, 2025
778eb35
Add curl-based cookie session script
zedeus Nov 17, 2025
a666c48
Include username in session logs if available
zedeus Nov 17, 2025
0bb0b7e
Support grok_share card
zedeus Nov 17, 2025
bb6eb81
Add support for tweet views
zedeus Nov 17, 2025
886f2d2
Bump API versions, use more SessionAwareUrls
zedeus Nov 17, 2025
6b655cd
Cleanup
zedeus Nov 17, 2025
e8de183
Fix broken pinned tweet parsing
zedeus Nov 17, 2025
824a7e3
Fix rss icon tag
zedeus Nov 17, 2025
78d788b
Fix verified parsing for oauth endpoints
zedeus Nov 19, 2025
b0d9c1d
Update endpoints, fix parser, remove quotes stat
zedeus Nov 22, 2025
f8a17fd
Remove Nim 1.6.x support
zedeus Nov 23, 2025
5b4a3fe
Redirect /i/status/id/history to /i/status/id
zedeus Nov 23, 2025
53edbbc
Fix broken tweet pagination ("Load more" button)
zedeus Nov 23, 2025
25df682
Expose username as HTML attribute
zedeus Nov 24, 2025
1657eeb
Fix canonical link causing redirects to Twitter
zedeus Nov 24, 2025
d47eb8f
Fix double slashes in url replacements
zedeus Nov 24, 2025
4748311
Fix intent/follow URL redirect
zedeus Nov 24, 2025
f038b53
Fix body font size to match x.com
zedeus Nov 24, 2025
4979d07
Add spaces filter, remove broken filters
zedeus Nov 24, 2025
12bbddf
Update search panel grid layout and animation
zedeus Nov 24, 2025
78101df
Style number input field
zedeus Nov 24, 2025
2b922c0
Embed quote tweet in RSS (#1316)
zedeus Nov 25, 2025
404b06b
Include "Video" and link for video tweets in RSS (#1315)
zedeus Nov 25, 2025
b83227a
Implement temp fix for cookie sessions
zedeus Nov 25, 2025
8516ebe
Fix 'key not found in object: expanded_url' error
zedeus Nov 28, 2025
dae68b4
Ignore null errors, they're internal API errors
zedeus Nov 29, 2025
31d210c
Add experimental x-client-transaction-id support (#1324)
zedeus Nov 29, 2025
7a08a9e
Format css
zedeus Nov 29, 2025
96ec75f
Add video duration to overlay
zedeus Nov 29, 2025
436a873
Improve verified checkmark icon, css improvements
zedeus Nov 29, 2025
71e65c8
Round video duration properly
zedeus Nov 29, 2025
064ec88
Transition to ID-only RSS GUIDs on Dec 14, 2025
zedeus Nov 30, 2025
4b9aec6
Use graphTweet for cookie sessions for now
zedeus Nov 30, 2025
a62ec9c
Normalize headers
zedeus Nov 30, 2025
7734d97
Add username validation
zedeus Nov 30, 2025
693a189
Add heuristics to detect when to show "Load more"
zedeus Nov 30, 2025
e741385
Allow , in username to support multiple users
zedeus Nov 30, 2025
17fc262
Minor fix
zedeus Nov 30, 2025
663f5a5
Improve headers
zedeus Dec 6, 2025
51b5485
Add preliminary support for nitter-proxy
zedeus Dec 6, 2025
793a034
Merge remote-tracking branch 'refs/remotes/upstream/master'
LeifXu Dec 6, 2025
fb52895
feat: add session creation tool with Puppeteer and dependencies
LeifXu Dec 7, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
108 changes: 108 additions & 0 deletions .github/workflows/run-tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
name: Tests

on:
push:
paths-ignore:
- "*.md"
branches-ignore:
- master
workflow_call:

# Ensure that multiple runs on the same branch do not overlap.
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

defaults:
run:
shell: bash

jobs:
build-test:
name: Build and test
runs-on: buildjet-2vcpu-ubuntu-2204
strategy:
matrix:
nim: ["2.0.x", "2.2.x", "devel"]
steps:
- name: Checkout Code
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Cache Nimble Dependencies
id: cache-nimble
uses: buildjet/cache@v4
with:
path: ~/.nimble
key: ${{ matrix.nim }}-nimble-v2-${{ hashFiles('*.nimble') }}
restore-keys: |
${{ matrix.nim }}-nimble-v2-

- name: Setup Nim
uses: jiro4989/setup-nim-action@v2
with:
nim-version: ${{ matrix.nim }}
use-nightlies: true
repo-token: ${{ secrets.GITHUB_TOKEN }}

- name: Build Project
run: nimble build -d:release -Y

integration-test:
needs: [build-test]
name: Integration test
runs-on: buildjet-2vcpu-ubuntu-2204
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Cache Nimble Dependencies
id: cache-nimble
uses: buildjet/cache@v4
with:
path: ~/.nimble
key: devel-nimble-v2-${{ hashFiles('*.nimble') }}
restore-keys: |
devel-nimble-v2-

- name: Setup Python (3.10) with pip cache
uses: buildjet/setup-python@v4
with:
python-version: "3.10"
cache: pip

- name: Setup Nim
uses: jiro4989/setup-nim-action@v2
with:
nim-version: devel
use-nightlies: true
repo-token: ${{ secrets.GITHUB_TOKEN }}

- name: Build Project
run: nimble build -d:release -Y

- name: Install SeleniumBase and Chromedriver
run: |
pip install seleniumbase
seleniumbase install chromedriver

- name: Start Redis Service
uses: supercharge/[email protected]

- name: Prepare Nitter Environment
run: |
sudo apt-get update && sudo apt-get install -y libsass-dev
cp nitter.example.conf nitter.conf
sed -i 's/enableDebug = false/enableDebug = true/g' nitter.conf
nimble md
nimble scss
echo '${{ secrets.SESSIONS }}' | head -n1
echo '${{ secrets.SESSIONS }}' > ./sessions.jsonl

- name: Run Tests
run: |
./nitter &
pytest -n1 tests
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,6 @@ nitter.conf
guest_accounts.json*
sessions.json*
dump.rdb

node_modules
debug_responses
2 changes: 2 additions & 0 deletions nitter.example.conf
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ enableJsonApi = true # set this to false to disable the JSON API
enableDebug = false # enable request logs and debug endpoints (/.sessions)
proxy = "" # http/https url, SOCKS proxies are not supported
proxyAuth = ""
apiProxy = "" # nitter-proxy host, e.g. localhost:7000
disableTid = false # enable this if cookie-based auth is failing

# Change default preferences here, see src/prefs_impl.nim for a complete list
[Preferences]
Expand Down
2 changes: 1 addition & 1 deletion nitter.nimble
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ bin = @["nitter"]

# Dependencies

requires "nim >= 1.6.10"
requires "nim >= 2.0.0"
requires "jester#baca3f"
requires "karax#5cf360c"
requires "sass#7dfdd03"
Expand Down
145 changes: 115 additions & 30 deletions public/css/fontello.css
Original file line number Diff line number Diff line change
@@ -1,53 +1,138 @@
@font-face {
font-family: 'fontello';
src: url('/fonts/fontello.eot?21002321');
src: url('/fonts/fontello.eot?21002321#iefix') format('embedded-opentype'),
url('/fonts/fontello.woff2?21002321') format('woff2'),
url('/fonts/fontello.woff?21002321') format('woff'),
url('/fonts/fontello.ttf?21002321') format('truetype'),
url('/fonts/fontello.svg?21002321#fontello') format('svg');
font-family: "fontello";
src: url("/fonts/fontello.eot?77185648");
src:
url("/fonts/fontello.eot?77185648#iefix") format("embedded-opentype"),
url("/fonts/fontello.woff2?77185648") format("woff2"),
url("/fonts/fontello.woff?77185648") format("woff"),
url("/fonts/fontello.ttf?77185648") format("truetype"),
url("/fonts/fontello.svg?77185648#fontello") format("svg");
font-weight: normal;
font-style: normal;
}

[class^="icon-"]:before, [class*=" icon-"]:before {
[class^="icon-"]:before,
[class*=" icon-"]:before {
font-family: "fontello";
font-style: normal;
font-weight: normal;
speak: never;

display: inline-block;
text-decoration: inherit;
width: 1em;
margin-right: 0.2em;
text-align: center;

/* For safety - reset parent styles, that can break glyph codes*/
font-variant: normal;
text-transform: none;

/* fix buttons height, for twitter bootstrap */
line-height: 1em;

/* Font smoothing. That was taken from TWBS */
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}

.icon-heart:before { content: '\2665'; } /* '♥' */
.icon-quote:before { content: '\275e'; } /* '❞' */
.icon-comment:before { content: '\e802'; } /* '' */
.icon-ok:before { content: '\e803'; } /* '' */
.icon-play:before { content: '\e804'; } /* '' */
.icon-link:before { content: '\e805'; } /* '' */
.icon-calendar:before { content: '\e806'; } /* '' */
.icon-location:before { content: '\e807'; } /* '' */
.icon-picture:before { content: '\e809'; } /* '' */
.icon-lock:before { content: '\e80a'; } /* '' */
.icon-down:before { content: '\e80b'; } /* '' */
.icon-retweet:before { content: '\e80d'; } /* '' */
.icon-search:before { content: '\e80e'; } /* '' */
.icon-pin:before { content: '\e80f'; } /* '' */
.icon-cog:before { content: '\e812'; } /* '' */
.icon-rss-feed:before { content: '\e813'; } /* '' */
.icon-info:before { content: '\f128'; } /* '' */
.icon-bird:before { content: '\f309'; } /* '' */

.icon-views:before {
content: "\e800";
}

/* '' */
.icon-heart:before {
content: "\e801";
}

/* '' */
.icon-quote:before {
content: "\e802";
}

/* '' */
.icon-comment:before {
content: "\e803";
}

/* '' */
.icon-play:before {
content: "\e805";
}

/* '' */
.icon-link:before {
content: "\e806";
}

/* '' */
.icon-calendar:before {
content: "\e807";
}

/* '' */
.icon-location:before {
content: "\e808";
}

/* '' */
.icon-picture:before {
content: "\e809";
}

/* '' */
.icon-lock:before {
content: "\e80a";
}

/* '' */
.icon-down:before {
content: "\e80b";
}

/* '' */
.icon-retweet:before {
content: "\e80c";
}

/* '' */
.icon-search:before {
content: "\e80d";
}

/* '' */
.icon-pin:before {
content: "\e80e";
}

/* '' */
.icon-cog:before {
content: "\e80f";
}

/* '' */
.icon-rss:before {
content: "\e810";
}

/* '' */
.icon-ok:before {
content: "\e811";
}

/* '' */
.icon-circle:before {
content: "\f111";
}

/* '' */
.icon-info:before {
content: "\f128";
}

/* '' */
.icon-bird:before {
content: "\f309";
}

/* '' */
18 changes: 9 additions & 9 deletions public/fonts/LICENSE.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,15 @@
Font license info


## Modern Pictograms

Copyright (c) 2012 by John Caserta. All rights reserved.

Author: John Caserta
License: SIL (http://scripts.sil.org/OFL)
Homepage: http://thedesignoffice.org/project/modern-pictograms/


## Entypo

Copyright (C) 2012 by Daniel Bruce
Expand Down Expand Up @@ -37,12 +46,3 @@ Font license info
Homepage: http://aristeides.com/


## Modern Pictograms

Copyright (c) 2012 by John Caserta. All rights reserved.

Author: John Caserta
License: SIL (http://scripts.sil.org/OFL)
Homepage: http://thedesignoffice.org/project/modern-pictograms/


Binary file modified public/fonts/fontello.eot
Binary file not shown.
34 changes: 19 additions & 15 deletions public/fonts/fontello.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified public/fonts/fontello.ttf
Binary file not shown.
Binary file modified public/fonts/fontello.woff
Binary file not shown.
Binary file modified public/fonts/fontello.woff2
Binary file not shown.
Loading
Loading