GitHub API (PyGithub)
raw JSON → 2.8.1 verified Tue May 12 auth: no python install: verified quickstart: verified
Community-maintained Python library for GitHub REST API v3. Current version is 2.8.1 (Feb 2026). Note: package name on PyPI is 'PyGithub' (capital P and G) but imports as 'github' (lowercase). Not an official GitHub SDK.
pip install PyGithub Common errors
error ModuleNotFoundError: No module named 'github' ↓
cause The PyGithub package is not installed or is installed in a different Python environment.
fix
Ensure PyGithub is installed in your current environment using: pip install PyGithub
error ImportError: cannot import name 'Auth' from 'github' ↓
cause The 'Auth' module is not available in the installed version of PyGithub.
fix
Use the older authentication method: from github import Github; g = Github('access_token')
error ImportError: cannot import name 'GitHub' from 'github' ↓
cause The class name is case-sensitive; 'GitHub' should be 'Github'.
fix
Correct the import statement to: from github import Github
error AttributeError: 'Repository' object has no attribute 'get_contents' ↓
cause The 'get_contents' method is not available in the 'Repository' class.
fix
Use the 'get_dir_contents' method instead: contents = repo.get_dir_contents('path')
error TypeError: 'NoneType' object is not iterable ↓
cause A method returned None, possibly due to an invalid repository or user.
fix
Ensure the repository or user exists and is accessible: repo = g.get_repo('owner/repo')
Warnings
breaking Github(login_or_token='token') is the old 1.x pattern. In 2.x use Auth.Token() and pass via auth= argument. ↓
fix auth = Auth.Token('ghp_...'); g = Github(auth=auth)
breaking Commit.files used to return list[File], now returns PaginatedList[File]. len(commit.files) raises TypeError. ↓
fix Use commit.files.totalCount or iterate instead of len()
breaking repo.compare().commits used to return list[Commit], now returns PaginatedList[Commit]. len() raises TypeError. ↓
fix Use .totalCount property instead of len()
breaking datetime objects returned by the API are now timezone-aware (UTC). Comparing with naive datetime instances breaks. ↓
fix Add tzinfo=timezone.utc to any datetime instances used in comparisons
gotcha pip install name is PyGithub (capital P, G) but the import is 'from github import Github'. The casing mismatch trips up agents constantly. ↓
fix pip install PyGithub && from github import Github
gotcha g.close() must be called after use to close the underlying connection pool. Omitting causes ResourceWarning in tests. ↓
fix Use as context manager: with Github(auth=auth) as g: ...
gotcha PullRequest.create_review_comment argument renamed from position= to line=. Keyword callers break silently. ↓
fix Replace position=N with line=N
gotcha This is a community SDK, not an official GitHub product. GitHub has no official Python SDK. Agents often assume otherwise. ↓
fix For official REST access use requests + Authorization header directly, or use PyGithub.
breaking The provided GitHub token is invalid, expired, or lacks the necessary permissions (e.g., 'public_repo' for public repos, 'repo' for private). This results in a BadCredentialsException. ↓
fix Ensure the GitHub token is correct, not expired, and has the required scopes for the API calls being made. Check GitHub token settings or regenerate a new token with appropriate permissions.
Install compatibility verified last tested: 2026-05-12
python os / libc status wheel install import disk
3.10 alpine (musl) - - 0.82s 44.7M
3.10 slim (glibc) - - 0.61s 45M
3.11 alpine (musl) - - 1.11s 48.3M
3.11 slim (glibc) - - 0.93s 49M
3.12 alpine (musl) - - 1.38s 39.8M
3.12 slim (glibc) - - 1.37s 40M
3.13 alpine (musl) - - 0.87s 39.5M
3.13 slim (glibc) - - 0.91s 40M
3.9 alpine (musl) - - 0.81s 44.8M
3.9 slim (glibc) - - 0.71s 45M
Imports
- Github, Auth wrong
import PyGithubcorrectfrom github import Github, Auth
Quickstart verified last tested: 2026-05-12
from github import Github, Auth
auth = Auth.Token("your_token")
g = Github(auth=auth)
repo = g.get_repo("owner/repo")
for issue in repo.get_issues(state='open'):
print(issue.title)
g.close()