{"id":102,"library":"pygithub","title":"PyGithub","description":"Python library to access the GitHub REST API v3. Provides typed Python objects for repositories, issues, pull requests, users, organizations, and more. Built on top of requests. Current version is 2.6.0 (2025). Supports Python 3.8+.","status":"active","version":"2.6.0","language":"python","source_language":"en","source_url":"https://github.com/PyGithub/PyGithub","tags":["github","api","rest","git","repositories","python","automation"],"install":[{"cmd":"pip install PyGithub","lang":"bash","label":"Python"}],"dependencies":[{"reason":"Required for GitHub App authentication via PyJWT and cryptography.","package":"PyGithub[integrations]","optional":true}],"imports":[{"note":"The package name on PyPI is PyGithub but the import module is 'github', not 'pygithub'.","wrong":"import pygithub","symbol":"Github","correct":"from github import Github"},{"note":"Since v2.0 the login_or_token parameter is removed. Use Auth.Token() objects instead.","wrong":"Github(login_or_token='my_token')","symbol":"Auth","correct":"from github import Auth"},{"note":"Used for GitHub App authentication. Requires the [integrations] extra.","symbol":"GithubIntegration","correct":"from github import GithubIntegration"}],"quickstart":{"code":"import os\nfrom github import Github, Auth\n\ntoken = os.environ.get('GITHUB_TOKEN', '')\nauth = Auth.Token(token)\ng = Github(auth=auth)\n\nrepo = g.get_repo('PyGithub/PyGithub')\nprint(f'Repo: {repo.full_name}')\nprint(f'Stars: {repo.stargazers_count}')\n\n# List open issues\nfor issue in repo.get_issues(state='open')[:5]:\n    print(f'  #{issue.number}: {issue.title}')\n\ng.close()","lang":"python","description":"Minimal example: authenticate with a personal access token and list repository info and issues."},"warnings":[{"fix":"Replace Github(login_or_token='TOKEN') with Github(auth=Auth.Token('TOKEN')).","message":"In v2.0, the login_or_token, password, and jwt parameters on Github() were removed. Authentication must use Auth objects.","severity":"breaking","affected_versions":">= 2.0.0"},{"fix":"Use 'from github import Github' not 'import pygithub'.","message":"The import module name is 'github', not 'pygithub'. Using 'import pygithub' raises ModuleNotFoundError.","severity":"breaking","affected_versions":"all"},{"fix":"Use totalCount before iterating, slice results, or check g.get_rate_limit() to monitor usage.","message":"PaginatedList objects are lazily loaded. Iterating over get_issues(), get_pulls(), etc. makes one API call per page (default 30 items). Large repos can exhaust rate limits quickly.","severity":"gotcha","affected_versions":"all"},{"fix":"Use 'with Github(auth=auth) as g:' or explicitly call g.close() when done.","message":"Github objects hold a requests Session. Failing to call g.close() or use a context manager leaks connections.","severity":"gotcha","affected_versions":"all"},{"fix":"Check g.get_rate_limit().core.remaining and implement retry logic or use retry_after from the RateLimitExceededException.","message":"GitHub API rate limit is 5000 requests/hour for authenticated users, 60/hour for unauthenticated. PyGithub does not auto-retry on 403 rate limit errors.","severity":"gotcha","affected_versions":"all"},{"fix":"Use GithubIntegration(auth=Auth.AppAuth(app_id, private_key)) instead of positional arguments.","message":"GithubIntegration constructor parameters changed in v2.0. The old positional (integration_id, private_key) signature is removed.","severity":"deprecated","affected_versions":">= 2.0.0"},{"fix":"Ensure that the authentication token passed to Auth.Token() is a valid, non-empty string.","message":"The token provided to Auth.Token() must be a non-empty string. An AssertionError: assert len(token) > 0 indicates an empty or invalid token was passed during authentication.","severity":"breaking","affected_versions":"all"},{"fix":"Ensure the token passed to Auth.Token() is a non-empty string. Verify the environment variable or configuration storing the token is correctly set and not empty.","message":"Auth.Token() raises AssertionError if the token provided is an empty string. A valid, non-empty GitHub Personal Access Token is required.","severity":"breaking","affected_versions":"all"}],"env_vars":null,"last_verified":"2026-05-12T08:07:02.815Z","next_check":"2026-06-17T00:00:00.000Z","problems":[{"fix":"Ensure the library is installed with `pip install PyGithub` and then import the main class correctly using `from github import Github`.","cause":"The Python package is installed as `PyGithub` but developers often attempt to import it using `import github` or `from github import Github`, which refers to a module name that doesn't exist directly.","error":"ModuleNotFoundError: No module named 'github'"},{"fix":"Verify that your PAT is correct, active, and has the required scopes. For GitHub Enterprise, ensure the `base_url` parameter is set correctly when initializing the `Github` object, typically to `https://{hostname}/api/v3`. For PATs, initialize with `from github import Auth; auth = Auth.Token('YOUR_PAT'); g = Github(auth=auth)`.","cause":"This error occurs when the provided GitHub Personal Access Token (PAT) is invalid, expired, lacks the necessary permissions (scopes), or when an incorrect base URL is used for GitHub Enterprise.","error":"github.GithubException.GithubException: 401 {\"message\": \"Bad credentials\"}"},{"fix":"Consult the PyGithub documentation for the correct method names (e.g., `issue.get_comments()` instead of `issue.get_issue_comments()`). You can also use `dir(obj)` or `help(obj)` in a Python console to inspect available attributes and methods for an object.","cause":"This `AttributeError` typically arises when attempting to call a method or access an attribute that does not exist on a specific PyGithub object. Developers might guess method names (e.g., `get_issue_comments`) instead of consulting the actual API or using introspection.","error":"AttributeError: 'Issue' object has no attribute 'get_issue_comments'"},{"fix":"Ensure that the token string has no leading or trailing whitespace by using the `.strip()` method: `token = token_file.read().strip()` or `token = os.environ.get('GITHUB_TOKEN').strip()`.","cause":"This error often happens when a Personal Access Token (PAT) is read from a file or an environment variable and includes extraneous whitespace characters, such as a newline character (`\\n`), which makes the HTTP header invalid.","error":"ValueError: Invalid header value b'token <properly_formed_token>\\n'"}],"ecosystem":"pypi","meta_description":null,"install_score":100,"install_tag":"verified","quickstart_score":0,"quickstart_tag":"stale","pypi_latest":null,"install_checks":{"last_tested":"2026-05-12","tag":"verified","tag_description":"installs cleanly on critical runtimes, fast import, recently tested","results":[{"runtime":"python:3.10-alpine","python_version":"3.10","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.84,"mem_mb":17.3,"disk_size":"44.7M"},{"runtime":"python:3.10-slim","python_version":"3.10","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.62,"mem_mb":17.2,"disk_size":"45M"},{"runtime":"python:3.11-alpine","python_version":"3.11","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":1.11,"mem_mb":19.9,"disk_size":"48.3M"},{"runtime":"python:3.11-slim","python_version":"3.11","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.89,"mem_mb":19.8,"disk_size":"49M"},{"runtime":"python:3.12-alpine","python_version":"3.12","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":1.39,"mem_mb":19.7,"disk_size":"39.8M"},{"runtime":"python:3.12-slim","python_version":"3.12","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":1.34,"mem_mb":19.7,"disk_size":"40M"},{"runtime":"python:3.13-alpine","python_version":"3.13","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.92,"mem_mb":18.8,"disk_size":"39.5M"},{"runtime":"python:3.13-slim","python_version":"3.13","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.9,"mem_mb":18.8,"disk_size":"40M"},{"runtime":"python:3.9-alpine","python_version":"3.9","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.81,"mem_mb":17.9,"disk_size":"44.8M"},{"runtime":"python:3.9-slim","python_version":"3.9","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.74,"mem_mb":17.9,"disk_size":"45M"}]},"quickstart_checks":{"last_tested":"2026-05-12","tag":"stale","tag_description":"widespread failures or data too old to trust","results":[{"runtime":"python:3.10-alpine","exit_code":1},{"runtime":"python:3.10-slim","exit_code":1},{"runtime":"python:3.11-alpine","exit_code":1},{"runtime":"python:3.11-slim","exit_code":1},{"runtime":"python:3.12-alpine","exit_code":1},{"runtime":"python:3.12-slim","exit_code":1},{"runtime":"python:3.13-alpine","exit_code":1},{"runtime":"python:3.13-slim","exit_code":1},{"runtime":"python:3.9-alpine","exit_code":1},{"runtime":"python:3.9-slim","exit_code":1}]}}