Skip to content

Valid reddit_session works with curl/urllib but httpx transport returns Reddit 403 #13

Description

@aaajiao

Summary

A valid reddit_session cookie works against Reddit JSON endpoints with urllib and curl, but the native rdt-cli httpx transport gets a Reddit 403 HTML page for the same endpoints.

This appears distinct from #11 (cookie discovery) and #12 (subreddit listing HTTP 500). In this case the cookie is present and valid; the failure is specific to the httpx request path / transport fingerprint.

Environment

  • rdt-cli: 0.4.2, installed from GitHub main via uv tool
  • Python: 3.13.7
  • httpx: 0.28.1
  • OS: Linux aarch64 under OpenClaw/OrbStack sandbox
  • Auth: valid browser reddit_session cookie copied into ~/.config/rdt-cli/credential.json
  • Account: botisaaajiao

No raw cookie value is included here.

Credential sanity checks

The copied reddit_session value is a normal HTTP cookie string:

cookie_length: 729
ascii_printable: true
whitespace_count: 0

The same cookie succeeds when sent via non-httpx transports.

What works

Using the same reddit_session cookie and the same rdt_cli.fingerprint.BrowserFingerprint.chrome133_mac().read_headers() headers, urllib returns 200 JSON:

urllib /api/me.json?raw_json=1 200 application/json; charset=UTF-8
urllib /subreddits/mine/subscriber.json?raw_json=1 200 application/json; charset=UTF-8
urllib /.json?raw_json=1 200 application/json; charset=UTF-8

A local wrapper fallback using urllib can authenticate and read feed data successfully:

{
  "ok": true,
  "schema_version": "1",
  "data": {
    "authenticated": true,
    "cookie_count": 1,
    "username": "botisaaajiao",
    "capabilities": ["read"],
    "modhash_present": true,
    "error": null
  }
}

What fails

Native rdt-cli / httpx returns 403 HTML with the same cookie/header setup:

httpx /api/me.json?raw_json=1 403 text/html '<body class=theme-beta><div><style>.them'
httpx /subreddits/mine/subscriber.json?raw_json=1 403 text/html '<body class=theme-beta><div><style>.them'
httpx /.json?raw_json=1 403 text/html '<body class=theme-beta><div><style>.them'

Running the raw CLI with the workspace credential also reports forbidden rather than authenticated:

{
  "ok": true,
  "schema_version": "1",
  "data": {
    "authenticated": false,
    "cookie_count": 1,
    "source": "mac-exec:Chrome:Default:host-hash-stripped",
    "username": "botisaaajiao",
    "capabilities": ["read"],
    "modhash_present": false,
    "last_verified_at": null,
    "error": "Access forbidden: Resource"
  }
}

Minimal reproduction shape

The key comparison is:

import json
import pathlib
import urllib.request
import httpx
from rdt_cli.fingerprint import BrowserFingerprint

headers = BrowserFingerprint.chrome133_mac().read_headers()
cred = json.loads(pathlib.Path("~/.config/rdt-cli/credential.json").expanduser().read_text())
session = cred["cookies"]["reddit_session"]
url = "https://www.reddit.com/api/me.json?raw_json=1"

req = urllib.request.Request(url, headers={**headers, "Cookie": f"reddit_session={session}"})
with urllib.request.urlopen(req, timeout=20) as resp:
    print("urllib", resp.status, resp.headers.get("content-type"))

with httpx.Client(headers=headers, cookies={"reddit_session": session}, follow_redirects=True, timeout=20) as client:
    r = client.get(url)
    print("httpx", r.status_code, r.headers.get("content-type"), repr(r.text[:80]))

Observed result:

urllib 200 application/json; charset=UTF-8
httpx 403 text/html '<body class=theme-beta><div><style>...'

Expected behavior

If the cookie is valid and Reddit returns 200 for the same endpoint via urllib/curl, rdt-cli should either:

  1. make its httpx transport match a request fingerprint Reddit accepts, or
  2. provide a fallback transport for auth/feed reads, or
  3. surface this as a structured transport/fingerprint error instead of looking like an invalid credential.

Local workaround

For now I patched my workspace wrapper narrowly so rdt status and rdt feed --subs-only --compact fall back to urllib when raw rdt-cli reports forbidden. That restores my automation, but the upstream httpx path still fails.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions