X (Twitter) feed scraper with Docker container for autonomous operation.
cat > docker/.env << 'EOF'
GITHUB_TOKEN=ghp_xxx
EOFX blocks login from VPS environments. Export cookies from your browser:
- Install EditThisCookie Chrome extension
- Go to x.com while logged in
- Click extension → Export (copies JSON)
- Save as
cookies.jsonin repo root
# Local
./scripts/local-setup.sh
# VPS
./scripts/deploy.sh root@<VPS_IP>| Service | Local | VPS |
|---|---|---|
| API | http://localhost:8080 | http://<VPS_IP>:8080 |
| VNC | http://localhost:6080/vnc.html | http://<VPS_IP>:6080/vnc.html |
| Script | Description |
|---|---|
./scripts/local-setup.sh |
Build and run container locally |
./scripts/deploy.sh [host] |
Deploy to VPS |
./scripts/inject-cookies.sh [file] [host] |
Inject cookies into running container |
| Endpoint | Description |
|---|---|
GET /scrape?hours=N |
Run scraper (cached by default) |
GET /scrape?force |
Force fresh scrape |
GET /feed |
Get cached feed summary |
GET /feed/xml |
Get raw XML |
GET /cache/status |
Check cache age |
GET /cache/clear |
Clear cache |
GET /update |
Pull latest from GitHub + restart |
GET /inject-cookies |
Inject cookies |
GET /health |
Health check |
| Parameter | Default | Description |
|---|---|---|
hours |
0.5 | Time window to scrape |
feed |
following-recent | following-recent, following-popular, for-you |
no_reposts |
false | Exclude retweets |
force |
false | Bypass cache |
ttl |
(hours value) | Cache TTL in minutes (default: same as hours) |
{
"status": "success",
"summary": {
"post_count": 68,
"author_count": 12,
"hours": "2",
"top_authors": [
{"handle": "@example", "name": "Example", "post_count": 5}
],
"recent_posts": [
{
"author": "@example",
"content": "Tweet content...",
"url": "https://x.com/example/status/123",
"likes": 42,
"reposts": 5
}
]
}
}| Variable | Required | Description |
|---|---|---|
GITHUB_TOKEN |
Yes | GitHub PAT for private repo |
┌──────────────────────────────────────────────────────────────────────────┐
│ Docker Network │
│ │
│ ┌──────────────────┐ ┌─────────────────────────────────────────┐ │
│ │ openclaw │ │ xscrape │ │
│ │ (optional) │ │ │ │
│ │ │ HTTP │ ┌─────────────────────────────────┐ │ │
│ │ ┌────────────┐ │ │ │ API :8080 │ │ │
│ │ │ Agent/LLM │──┼───────▶│ │ /scrape - run scraper │ │ │
│ │ └────────────┘ │ │ │ /feed - get results │ │ │
│ │ │ │ │ /update - pull + restart │ │ │
│ └──────────────────┘ │ │ /inject-cookies │ │ │
│ │ └──────────────┬──────────────────┘ │ │
│ │ │ │ │
│ │ ▼ │ │
│ │ ┌─────────────────────────────────┐ │ │
│ │ │ scraper.py (Playwright) │ │ │
│ │ │ - human-like scrolling │ │ │
│ │ │ - feed selection │ │ │
│ │ │ - post collection │ │ │
│ │ └──────────────┬──────────────────┘ │ │
│ │ │ CDP │ │
│ │ ▼ │ │
│ │ ┌─────────────────────────────────┐ │ │
│ │ │ Chrome + Xvfb │ │ │
│ │ │ - stealth flags │ │ │
│ │ │ - CDP :9222 │ │ │
│ │ │ - VNC :6080 │ │ │
│ │ └─────────────────────────────────┘ │ │
│ │ │ │
│ └────────────────┬────────────────────────┘ │
│ │ │
└───────────────────────────────────────────────┼──────────────────────────┘
│ volume
▼
┌───────────────────────────┐
│ /data (xscrape-data) │
│ ├── cookies.json │
│ └── feed.xml │
└───────────────────────────┘
To use xscrape as an OpenClaw skill:
The OpenClaw config directory is bind-mounted into the container:
- Host:
/root/.openclaw/→ Container:/home/node/.openclaw/
# create skill directory and copy SKILL.md
ssh root@<VPS_IP> "mkdir -p /root/.openclaw/skills/xscrape"
scp SKILL.md root@<VPS_IP>:/root/.openclaw/skills/xscrape/
# fix permissions for node user (UID 1000)
ssh root@<VPS_IP> "chown -R 1000:1000 /root/.openclaw/skills/xscrape/"The xscrape container must be on the same Docker network as OpenClaw:
# connect xscrape to openclaw network
docker network connect openclaw_default xscrape
# verify connectivity
docker exec openclaw-openclaw-gateway-1 curl -s http://xscrape:8080/healthcd /opt/openclaw
docker compose restart openclaw-gateway
docker compose run --rm openclaw-cli skills list | grep xscrapeThe skill should show as ✓ ready. OpenClaw can now reach the API at http://xscrape:8080.
| Path | Description |
|---|---|
xscrape/ |
Python package (scraper, api, cookies) |
docker/ |
Dockerfile, entrypoint |
scripts/ |
Setup and deployment scripts |
SKILL.md |
OpenClaw agent skill definition |