Skip to main content

lukhed_x

A custom tweepy wrapper for the X API v2 with built-in key management via LukhedAuth. Used by @grindSunday and @popPunkPoets bots.

Features

  • X API v2: v1.1 endpoints are gone, this wrapper is v2 only
  • Flexible Key Management: Store API credentials locally or in a private GitHub repo
  • Cost Aware: every method documents what it costs to call
  • Posts, Users, Engagement, Lists, DMs and Media

Installation

pip install lukhed-x

Costs

X retired the free tier in 2026. Every call costs credits, which you buy at console.x.com. Full table: X API pricing.

The one to watch:

Action Cost
Create a post $0.015
Create a post containing a URL $0.200
Owned reads (your own posts, followers, mentions, lists) $0.001
Post / list reads $0.005
User and follower reads $0.010
Likes, reposts, follows, mutes, DMs $0.015
Undoing any of those $0.010

A link in your post text costs 13x a plain post. Keep URLs out of automated posts unless you mean it.

Set a spending cap in the developer console before running any bot.

Quick Start

Initial Setup

from lukhed_x import X

# First run prompts for your X API credentials, then stores them
x_client = X(handle="your_handle")

Basic Usage

from lukhed_x import X

x_client = X(handle="your_handle")

# Create a post
result = x_client.create_post("Hello, world!")
if not result["error"]:
    print(f"Posted: {result['url']}")
    print(f"Post ID: {result['postID']}")

# Post with an image
upload = x_client.upload_media("path/to/image.jpg")
x_client.create_post("Check out this image!", media_ids=[upload["mediaID"]])

# Reply
x_client.create_post(".@username Thanks for the great post!", reply_to_post_id="1234567890")

# Poll
x_client.create_post("Who wins?", poll_options=["Ravens", "Steelers"], poll_duration_minutes=1440)

# Read your own timeline (owned read, $0.001)
x_client.get_my_posts(max_results=10)

# Delete
x_client.delete_post("your_post_id")

Available Methods

Posts (write): create_post, delete_post, hide_reply, unhide_reply

Posts (read): get_post, get_posts, get_my_posts, get_user_posts, get_my_mentions, get_home_timeline, search_recent_posts, get_recent_post_counts, get_quote_posts, get_reposters, get_liking_users

Engagement: like_post, unlike_post, repost, unrepost, follow_user, unfollow_user, mute_user, unmute_user

Users: get_me, get_user, get_users, get_my_followers, get_my_following, get_user_followers, get_user_following, get_my_liked_posts, get_my_muted, get_my_blocked

Lists: create_list, update_list, delete_list, add_list_member, remove_list_member, get_list, get_list_posts, get_my_lists

DMs: send_dm, get_dm_events

Media: upload_media

Read methods accept any X API v2 field/expansion parameter as a keyword argument, e.g. get_my_posts(max_results=20, tweet_fields=["public_metrics"]).

X API Setup

  1. Create a developer account at developer.x.com
  2. Buy credits at console.x.com and set a spending cap
  3. Create an app with Read and Write permissions and generate credentials
  4. You'll need:
    • API Key
    • API Secret
    • Access Token
    • Access Token Secret
    • Bearer Token (optional, only for app-only endpoints like get_recent_post_counts)

For detailed instructions, visit the X API Getting Started Guide.

Key Management Options

Authentication is handled by LukhedAuth under the project name xapi, keyed by handle, so one install can drive multiple bot accounts.

GitHub Storage (Default)

x_client = X(handle="your_handle", key_management="github")

Stores credentials in a private GitHub repository, allowing access across different devices. You will need a github access token: Managing your personal access tokens

Local Storage

x_client = X(handle="your_handle", key_management="local")

Stores credentials in your local file system.

Provide Auth Directly

x_client = X(handle="your_handle", provide_auth={
    "apiKey": "...", "apiSecret": "...",
    "accessToken": "...", "accessTokenSecret": "..."
})

Error Handling

All methods return a consistent structure:

result = x_client.create_post("Hello!")
if result["error"]:
    print("Function Error:", result["errorData"]["functionError"])
    print("Tweepy Error:", result["errorData"]["tweepyError"])
else:
    print("Success:", result["url"])

Notes and Limitations

  • Auth: OAuth 1.0a user context. X still supports it for v2, but their docs now lead with OAuth 2.0, so expect a migration eventually.
  • Media upload: uses the v2 chunked flow (initialize / append / finalize). X documents those endpoints for OAuth 2.0 with the media.write scope, so OAuth 1.0a may return a 403.
  • Quote posts: quote_post_id now requires an Enterprise plan.
  • Bookmarks and Spaces: omitted, they need OAuth 2.0 user context.
  • Blocking: X removed the v2 write endpoints. get_my_blocked reads only.
  • Deprecated but kept: create_tweet, delete_tweet and get_my_user_info still work and return the same keys as before. create_tweet(image_data=...) now expects a file path.

Migrating from 0.1.x

  • X(..., x_api_setup=True) is gone. Setup runs automatically when no keys are found for a handle.
  • v1.1 methods and the version switching helpers are gone.
  • Existing stored keys keep working. Re-run setup only if you want to add a bearer token.

License

This project is licensed under the MIT License.

Support

For issues and questions, please open an issue on the GitHub repository.


Note: This wrapper is designed for legitimate bot usage and follows X's Terms of Service. Please ensure your bot complies with X's automation rules and rate limits.

Metadata

Release files for lukhed-x 0.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for lukhed-x 0.2.0
File Size Uploaded
lukhed_x-0.2.0.tar.gz 12.1 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for lukhed-x 0.2.0
File Interpreter ABI Platform
lukhed_x-0.2.0-py3-none-any.whl Python 3 none any Details

Total release size: 22.3 kB

Release files / lukhed_x-0.2.0.tar.gz

Download URL lukhed_x-0.2.0.tar.gz
Size 12.1 kB
Tags Source
SHA-256 checksum
How to use checksums
da3cf7302675820e6d6f5323be17ae13d7d6d6806c5fe54a4f4d6abc8a517c07
BLAKE2b-256 checksum
How to use checksums
fec9318c19432643c95ac4c21def0d8d0dd8b46dbb448a50a19b66c9e4c53ac8
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.0.1 CPython/3.11.9

Release files / lukhed_x-0.2.0-py3-none-any.whl

Download URL lukhed_x-0.2.0-py3-none-any.whl
Size 10.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
8e239e6ad37e48ed4a64f2ea52d85994d15a38540a8e86737a0dde3cffcbd322
BLAKE2b-256 checksum
How to use checksums
d493586afed3fc1031e6be96a6b7c7ffc553dd7885ca51d1b1c5b8da9877f398
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.0.1 CPython/3.11.9

Release history Release notifications | RSS feed

This release

0.2.0 This release

2 release files

0.1.2

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page