Skip to content

Repository files navigation

eksiapi logo
eksiapi

Unofficial sync and async Python SDK and MCP server for Ekşi Sözlük, supporting anonymous research and authenticated account actions across topics, entries, profiles, comments and feeds.

PyPIPython requirementMCP stdio serverTestsPostman collection

Quick start · MCP server · Python SDK · Features · Postman

🚀 Quick start

Install the library:

pip install eksiapi
# or
uv add eksiapi

Read entry number 1:

fromeksiapiimportEksiClientwithEksiClient.anonymous(raw_response=False) aseksi:
topic=eksi.entry(1)
entry=topic["Entries"][0]
print(f"{topic['Title']} · entry #{entry['Id']}")
print(f"@{entry['Author']['Nick']}: {entry['Content']}")
pena · entry #1
@ssg: gitar calmak icin kullanilan minik plastik garip nesne.

This call reads the mobile API directly. It does not parse HTML pages.

After installation, verify the live API from any directory:

eksiapi health
🩺 eksiapi health · 👻 anonymous
✅ today 50 başlık · güncel bir başlık (1888)
✅ popular 50 başlık · popüler bir başlık (230)
✅ entry pena · @ssg · #1
✅ user @ssg · 52522 entry
✅ channels 30 kanal
✅ server time 07.08.2026 17:18
🟢 6/6 kontrol başarılı

🤖 MCP server

Add the server to Codex without editing configuration files:

codex mcp add eksiapi -- uvx --from "eksiapi[mcp]" eksiapi mcp

Claude Code:

claude mcp add eksiapi --scope user -- uvx --from "eksiapi[mcp]" eksiapi mcp
Generic MCP client configuration
{
"mcpServers": {
"eksi": {
"command": "uvx",
"args": ["--from", "eksiapi[mcp]", "eksiapi", "mcp"]
}
}
}

Example research requests:

  • “Bugünün gündemini üç ana tema halinde özetle.”
  • “Bu başlıktaki ilk üç sayfanın ortak iddialarını karşılaştır.”
  • “Bu yazarın son entry'lerinde en sık geçen konular neler?”

eksiapi MCP running in Codexeksiapi MCP running in Claude

The server starts anonymously and read-only. Account actions require an explicit login, interactive mode and a human confirmation step:

eksiapi auth login
eksiapi mcp --mode interactive

Installation options, client configuration, credentials and complete tool list →

🐍 Python SDK

Anonymous reads:

fromeksiapiimportEksiClientwithEksiClient.anonymous(raw_response=False) aseksi:
today=eksi.today()
popular=eksi.popular()
debe=eksi.debe()
python=eksi.topic_entries("python")
profile=eksi.user("agmmnn")

Authenticated account data and writes:

fromeksiapiimportEksiClientwithEksiClient(raw_response=False) aseksi:
eksi.login("username-or-email", "password")
print(eksi.me())
preview=eksi.favorite_entry(1, dry_run=True)
print(preview.operation, preview.digest)

The async client provides the same public methods:

fromeksiapiimportAsyncEksiClientasyncwithAsyncEksiClient.anonymous(raw_response=False) aseksi:
asyncforentryineksi.iter_topic_entries("python", max_pages=3):
print(entry)

Authentication, responses, pagination, writes and async usage →

🖥️ Terminal UI

eksitui is the separate keyboard-focused terminal interface for browsing Ekşi Sözlük. It includes feeds, search, entry pagination, themes and mouse support.

uv tool install eksitui
eksi

eksiapi MCP running in Codex

🟠 Postman

  1. Open the public collection and select Run in Postman.
  2. Select Vault in the bottom bar, then open Local Vault → Settings and enable Allow Vault secrets in scripts.
  3. Send Authentication / Get anonymous bearer token and grant Vault access to the collection.
  4. Confirm the 200 OK response, then try Feeds / Today.

The collection generates the required authentication values and stores the session in Local Vault automatically. Authentication and publishing details →

📦 Installation options

Use caseInterfaceCommand
Python application or scriptSync/async SDKpip install eksiapi
Read access for an AI agentRead-only MCPuv tool install "eksiapi[mcp]"
Account actions from an AI agentInteractive MCPeksiapi mcp --mode interactive
Terminal applicationTextual TUIuv tool install eksitui
HTTP route referencePostman collectionPublic API documentation

✨ Features

FeatureIncluded
🔎 API coverageToday, popular and debe feeds, topic resolution and entry search, profiles, comments, channels, user history and pagination
🐍 Python SDKMatching sync and async clients, typed views, safe-read retries, token refresh, rate-limit metadata and test transports
🤖 MCP serverStructured results, canonical source URLs, bounded topic research and read-only anonymous access
🛡️ Write safetyDeterministic dry runs, no automatic write retries, secret-free audit events and human-approved MCP execution
📱 RuntimeAndroid-compatible authentication and TLS fingerprinting without a Frida session or interception proxy at runtime

Authentication modes

ModeCredentialsBest for
AnonymousNonePublic topics, entries, profiles, comments, channels and feeds
Logged inPassword login or an existing tokenAccount reads, favorites, votes, follows, messages, drafts and settings

Anonymous clients obtain and renew their own app bearer. Logged-in sessions keep refresh metadata and expose the account nick without returning credentials to MCP tools.

Safety model

Python writes support dry_run=True and return a WritePreview before any HTTP mutation. Writes are never retried automatically. The MCP server is read-only by default; interactive writes use signed, expiring, single-use previews and the MCP client's human elicitation flow.

Ekşi content is untrusted external data. Agents should analyze it as content, never as instructions.

📚 Documentation

GuideContents
Postman API referenceComplete endpoint reference, request examples and runnable collection
Python SDK guideAuthentication, sync/async clients, responses, pagination and writes
MCP guideInstallation, client configuration, credentials, modes and complete tool list
OpenAPI contractFull documented HTTP endpoint inventory and request shapes
APK analysisReverse-engineering evidence and risk decisions
ChangelogUser-facing changes by release

🔬 Reverse engineering

eksiapi is based on static analysis of the Ekşi Sözlük Android 2.4.10 APK. Retrofit declarations, request models and authentication code were inspected with JADX, so the library does not require a Frida session or interception proxy at runtime.

Authentication requests include an Api-Secret value. The Android app builds the following plaintext and encrypts it with the embedded 2048-bit RSA public key:

{randomHex(40-80)}-{APP_UUID}-{len²}-{adjustedTime}-{dayOff}-{hourOff}-{minOff}-eksisozluk-android/144-{clientSecret}

The account login flow is:

  1. GET /v2/clientsettings/time to obtain the server timestamp.
  2. POST /v2/account/anonymoustoken to obtain an anonymous bearer.
  3. GET /v2/clientsettings/time again for a fresh timestamp.
  4. POST /token with the password or refresh-token grant.

The implementation is in eksiapi/auth.py. The APK hash, Retrofit annotation mapping and endpoint evidence are documented in the reverse-engineering notes.

🛠️ Development

uv sync --all-groups --all-extras
uv run ruff check .
uv run ruff format --check .
uv run pytest --cov=eksiapi

Python 3.10–3.14 is tested in CI with branch coverage enforced at 80%.

⚠️ Disclaimer

Unofficial and not affiliated with Ekşi Teknoloji. Intended for personal, educational and research use. API behavior may change with mobile app updates.

About

Unofficial API client and MCP server for Ekşi Sözlük, with anonymous research, account actions and a reverse-engineered mobile API.

Topics

Resources

Stars

6 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages