Skip to main content

Python SDK for the Product Hunt API v2

Project description

Product Hunt SDK

A Python SDK for the Product Hunt API. Track trending products, discover new launches, and monitor your own products.

Live Demo - See today's top Product Hunt launches, updated every 5 minutes.

Table of Contents

Installation

# With pip
pip install producthunt-sdk

# With uv
uv add producthunt-sdk

Requirements: Python 3.13+

Quick Start

from producthunt_sdk import ProductHuntClient, BearerAuth

client = ProductHuntClient(auth=BearerAuth("your_developer_token"))

# Get today's top products
for post in client.get_posts(featured=True, first=5).nodes:
    print(f"{post.name} - {post.votes_count} votes")

Get your token at producthunt.com/v2/oauth/applications

Authentication

Three authentication methods are available depending on your use case.

Developer Token

The simplest way to get started. Get a token from your Product Hunt dashboard.

from producthunt_sdk import ProductHuntClient, BearerAuth

client = ProductHuntClient(auth=BearerAuth("your_developer_token"))
posts = client.get_posts(featured=True)

Developer tokens provide full API access including user-specific data for your own account.

Client Credentials

Use for server-side applications that don't need user context. No browser required.

from producthunt_sdk import ProductHuntClient, ClientCredentials

client = ProductHuntClient(auth=ClientCredentials(
    client_id="your_client_id",
    client_secret="your_client_secret",
))

# Access public data - token is fetched automatically
posts = client.get_posts(featured=True)
for post in posts.nodes:
    print(f"{post.name}: {post.votes_count} votes")

Limitations: Client credentials only provide read access to public data. User-specific fields (is_voted, viewer, etc.) return default values.

OAuth

Use when building apps that authenticate users. This gives you access to the authenticated user's own data.

Note: Product Hunt requires HTTPS redirect URIs. Use ngrok to tunnel to localhost for development.

from producthunt_sdk import ProductHuntClient, OAuth2

# OAuth flow runs automatically on first request
client = ProductHuntClient(auth=OAuth2(
    client_id="your_client_id",
    client_secret="your_client_secret",
    redirect_uri="https://your-app.ngrok.io/callback",
))

# This triggers the OAuth flow: opens browser, waits for callback, exchanges token
viewer = client.get_viewer()
print(f"Logged in as @{viewer.user.username}")

# Token is cached - subsequent requests use the cached token
posts = client.get_user_posts(username=viewer.user.username)

See examples/oauth_flow.py for a complete example.

Token Caching

Tokens are cached in memory by default. For persistence across restarts:

from producthunt_sdk import OAuth2, ClientCredentials, TokenCache

# Use file-based cache
OAuth2.token_cache = TokenCache("~/.producthunt_tokens.json")
ClientCredentials.token_cache = TokenCache("~/.producthunt_tokens.json")

Usage Examples

Track Your Launch

post = client.get_post(slug="your-product")
print(f"Votes: {post.votes_count}")
print(f"Comments: {post.comments_count}")
print(f"Rating: {post.reviews_rating}")

Find Trending Products

from datetime import datetime, timedelta, UTC
from producthunt_sdk import PostsOrder

# Top AI products from the last week
posts = client.get_posts(
    topic="artificial-intelligence",
    posted_after=datetime.now(UTC) - timedelta(days=7),
    order=PostsOrder.VOTES,
    first=10
)

for post in posts.nodes:
    print(f"{post.name}: {post.tagline}")

Read Comments

from producthunt_sdk import CommentsOrder

comments = client.get_post_comments(
    post_slug="chatgpt",
    first=10,
    order=CommentsOrder.VOTES_COUNT
)
for comment in comments.nodes:
    print(f"{comment.body[:100]}...")

Monitor Topics

from producthunt_sdk import TopicsOrder

topics = client.get_topics(order=TopicsOrder.FOLLOWERS_COUNT, first=10)
for topic in topics.nodes:
    print(f"{topic.name}: {topic.followers_count} followers, {topic.posts_count} products")

Access Your Own Data

# Get your profile (requires your token)
viewer = client.get_viewer()
print(f"Logged in as: @{viewer.user.username}")

# Get your own posts
my_posts = client.get_user_posts(username=viewer.user.username)
for post in my_posts.nodes:
    print(f"{post.name} - {post.votes_count} votes")

Async Support

For high-performance applications:

import asyncio
from producthunt_sdk import AsyncProductHuntClient, BearerAuth

async def main():
    async with AsyncProductHuntClient(auth=BearerAuth("your_token")) as client:
        posts = await client.get_posts(featured=True)
        print(f"Found {len(posts.nodes)} products")

asyncio.run(main())

Custom GraphQL

Need something specific? Use raw GraphQL:

data = client.graphql("""
    query {
        posts(first: 5, featured: true) {
            edges {
                node {
                    name
                    votesCount
                }
            }
        }
    }
""")

API Reference

Available Methods

Method Description Access
get_post(id, slug) Get a single product Public
get_posts(...) List products with filters Public
get_topic(id, slug) Get a topic/category Public
get_topics(...) List topics Public
get_collection(id, slug) Get a curated collection Public
get_collections(...) List collections Public
get_collection_posts(...) Products in a collection Public
get_post_comments(...) Comments on a product Public (user info redacted)
get_post_votes(...) Votes on a product Public (user info redacted)
get_comment(id) Get a single comment Public (user info redacted)
get_viewer() Current authenticated user Your data only
get_user(id, username) Get user profile Your data only
get_user_posts(...) Products made by user Your data only
get_user_voted_posts(...) Products user upvoted Your data only
get_user_followers(...) User's followers Your data only
get_user_following(...) Who user follows Your data only
follow_user(user_id) Follow a user Requires write scope
unfollow_user(user_id) Unfollow a user Requires write scope
graphql(query, variables) Run custom GraphQL Varies

Pagination

All list methods return paginated results:

# First page
page1 = client.get_posts(first=20)

# Next page
if page1.page_info.has_next_page:
    page2 = client.get_posts(first=20, after=page1.page_info.end_cursor)

# Iterate all items
for post in page1.nodes:
    print(post.name)

Configuration

from producthunt_sdk import ProductHuntClient, BearerAuth

client = ProductHuntClient(
    auth=BearerAuth("your_token"),
    auto_wait_on_rate_limit=True,  # Wait instead of failing (default: True)
    max_wait_seconds=900,           # Max wait time for rate limits (default: 15min)
    timeout=30.0,                   # Request timeout (default: 30s)
    max_retries=3,                  # Retry on network errors (default: 3)
)

Rate Limits

The API allows 6,250 complexity points per 15 minutes. The SDK:

  • Tracks your usage automatically
  • Waits when you hit the limit (configurable)
  • Retries on network errors and server issues

Check your usage:

info = client.rate_limit_info
print(f"Remaining: {info.remaining}/{info.limit}")
print(f"Resets in: {info.seconds_until_reset:.0f}s")

Error Handling

from producthunt_sdk import (
    ProductHuntError,
    AuthenticationError,
    RateLimitError,
    GraphQLError,
)

try:
    posts = client.get_posts()
except AuthenticationError:
    print("Check your API token")
except RateLimitError as e:
    print(f"Rate limited. Retry in {e.rate_limit_info.seconds_until_reset}s")
except GraphQLError as e:
    print(f"API error: {e.message}")
except ProductHuntError as e:
    print(f"Something went wrong: {e}")

Data Access Limitations

Product Hunt's API has privacy restrictions:

Data Access
Featured/trending posts Full access
Post details (votes, comments count) Full access
Topics and collections Full access
Comments on posts Text only (commenter info redacted)
Your own profile, posts, votes, followers Full access
Other users' profiles, posts, votes, followers Redacted

For extended access to user data, contact Product Hunt at hello@producthunt.com.

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

producthunt_sdk-0.2.0.tar.gz (49.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

producthunt_sdk-0.2.0-py3-none-any.whl (20.2 kB view details)

Uploaded Python 3

File details

Details for the file producthunt_sdk-0.2.0.tar.gz.

File metadata

  • Download URL: producthunt_sdk-0.2.0.tar.gz
  • Upload date:
  • Size: 49.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for producthunt_sdk-0.2.0.tar.gz
Algorithm Hash digest
SHA256 7f2cfd8c2bfda80313ca7cdd025c83ecbda2c5bf3354db0a6a736effe29d4d63
MD5 6bab091ff4d7af7e4a82bf0be33ad400
BLAKE2b-256 10b8eca85ae2a525af389e01e1528a9b2924ed2028605db418062e0ac2450c3f

See more details on using hashes here.

Provenance

The following attestation bundles were made for producthunt_sdk-0.2.0.tar.gz:

Publisher: publish.yml on Domoryonok/producthunt-sdk

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file producthunt_sdk-0.2.0-py3-none-any.whl.

File metadata

File hashes

Hashes for producthunt_sdk-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 102c930f9fa4655255d2f7b13e3f508fd8e783d05e2b5bde8992a38c7f4ea5fd
MD5 05c8b3887084237fdd4bd3eb3cc56e5e
BLAKE2b-256 542227afd11342aba9e978a893b50de75f8ba39cef3338f161a26ee684f7c009

See more details on using hashes here.

Provenance

The following attestation bundles were made for producthunt_sdk-0.2.0-py3-none-any.whl:

Publisher: publish.yml on Domoryonok/producthunt-sdk

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page