---
name: package
description: "PyGithub package guide for Python with token auth, GitHub App auth, pagination, and version-aware API usage"
metadata:
  languages: "python"
  versions: "2.6.0"
  revision: 1
  updated-on: "2026-03-11"
  source: maintainer
  tags: "pygithub,github,api,auth,pagination,github-apps"
---

# PyGithub 2.6.0 Python Package Guide

## What It Is

`PyGithub` is the official-ish Python wrapper around the GitHub REST API from the PyGithub project. In code, you import from `github`, create a `Github(...)` client, and work with lazy objects such as users, repositories, issues, pull requests, and installations.

Use it when you need:

- authenticated GitHub API access from Python
- a higher-level object model instead of hand-writing REST requests
- GitHub App installation-token flows
- pagination helpers for large result sets

Package identity:

- Ecosystem: `pypi`
- Package: `PyGithub`
- Import root: `github`
- Version covered: `2.6.0`
- Docs root: `https://pygithub.readthedocs.io/en/stable/`
- Registry: `https://pypi.org/project/PyGithub/`
- Repository: `https://github.com/PyGithub/PyGithub`

Version-sensitive note:

- This guide is pinned to `2.6.0`, the version used here for this session.
- As of 2026-03-11, PyPI shows `2.8.1` as the latest release.
- The `stable/` docs root moves with the latest stable series, so treat it as current upstream guidance and keep your project lockfile as the final authority when behavior differs.

## Install

`2.6.0` requires Python `>=3.8`.

```bash
python -m pip install PyGithub==2.6.0
```

If you are reproducing existing project behavior, pin the version explicitly. A lot of online PyGithub snippets still target older 1.x APIs.

## Authentication And Setup

PyGithub 2.x expects an auth object, not a raw token string passed positionally.

### Personal access token

```python
import os

from github import Auth, Github

auth = Auth.Token(os.environ["GITHUB_TOKEN"])

with Github(auth=auth) as gh:
    me = gh.get_user()
    print(me.login)
```

Notes:

- PyGithub does not auto-read `GITHUB_TOKEN` for you. Read environment variables in your app and pass the value explicitly.
- Fine-grained PATs and GitHub App tokens must include the repository and action permissions your code needs.
- Prefer the context-manager form or call `gh.close()` when you finish with the client.

### GitHub App auth

Use `GithubIntegration` to exchange app credentials for an installation token:

```python
import os

from github import Auth, GithubIntegration

auth = Auth.AppAuth(
    os.environ["GITHUB_APP_ID"],
    os.environ["GITHUB_PRIVATE_KEY"],
)
integration = GithubIntegration(auth=auth)

installation = integration.get_repo_installation("OWNER", "REPO")
installation_auth = auth.get_installation_auth(installation.id)
```

You can then pass `installation_auth` into `Github(auth=installation_auth)` for normal repository operations.

### GitHub Enterprise Server

Point the client at the API root, not the web UI root:

```python
from github import Auth, Github

gh = Github(
    base_url="https://github.example.com/api/v3",
    auth=Auth.Token("TOKEN"),
)
```

## Core Usage

### Connect and fetch a repository

```python
from github import Auth, Github

with Github(auth=Auth.Token("TOKEN")) as gh:
    repo = gh.get_repo("octocat/Hello-World")
    print(repo.full_name)
    print(repo.default_branch)
```

`Github.get_repo("owner/name")` is the normal entry point for repository work.

### Read open issues lazily

```python
from github import Auth, Github

with Github(auth=Auth.Token("TOKEN"), per_page=50) as gh:
    repo = gh.get_repo("OWNER/REPO")
    issues = repo.get_issues(state="open")

    for issue in issues[:10]:
        print(issue.number, issue.title)
```

PyGithub collections are lazy `PaginatedList` objects. Slicing or iterating triggers API calls as needed.

### Create an issue

```python
from github import Auth, Github

with Github(auth=Auth.Token("TOKEN")) as gh:
    repo = gh.get_repo("OWNER/REPO")
    issue = repo.create_issue(
        title="Automated report",
        body="Generated by a scheduled job.",
    )
    print(issue.html_url)
```

This requires a token with issue-write permission on the target repository.

### Check rate limits

```python
from github import Auth, Github

with Github(auth=Auth.Token("TOKEN")) as gh:
    core_limit, core_remaining = gh.rate_limiting
    print(core_remaining, "of", core_limit)

    rate_limit = gh.get_rate_limit()
    print(rate_limit.core.remaining)
```

Unauthenticated clients work for some public data, but the rate limit is much lower. Prefer authenticated access in agent workflows.

## Pagination, Requests, And Tuning

### Fetch bounded pages

Use `get_page()` when you need explicit page-by-page control:

```python
from github import Auth, Github

with Github(auth=Auth.Token("TOKEN")) as gh:
    repo = gh.get_repo("OWNER/REPO")
    pulls = repo.get_pulls(state="open")

    first_page = pulls.get_page(0)
    for pr in first_page:
        print(pr.number, pr.title)
```

This is safer than forcing a whole collection into memory when a repository is large.

### Make a raw REST request

If PyGithub does not expose the endpoint you need cleanly, use the requester:

```python
from github import Auth, Github

with Github(auth=Auth.Token("TOKEN")) as gh:
    headers, data = gh.requester.requestJsonAndCheck(
        "GET",
        "/rate_limit",
    )
    print(data["resources"]["core"]["remaining"])
```

Keep the path relative to the API root. For GitHub Enterprise Server, that still goes through the `base_url` you configured on the client.

### Constructor options that matter

The `Github(...)` constructor in the official API docs exposes a few options that are useful in production code:

- `base_url` for GitHub Enterprise Server
- `timeout` for slow networks
- `per_page` to control page size
- `user_agent` when your integration needs a distinct UA string
- `verify` for TLS verification behavior
- `retry` for HTTP retry policy
- `pool_size` for connection reuse under concurrency

Only override these deliberately. The defaults are usually good enough for simple automation.

## Common Pitfalls

- Import from `github`, not `pygithub`. The package name and import name differ.
- Do not copy 1.x-era snippets like `Github("TOKEN")` into a `2.6.0` codebase. The 2.x docs standardize on `auth=Auth.Token(...)`.
- Do not rely on anonymous access for automation. GitHub rate limits unauthenticated requests aggressively.
- Do not forget to close the client. Use `with Github(...) as gh:` or call `gh.close()`.
- Do not convert large `PaginatedList` results into `list(...)` unless you actually need everything in memory.
- Do not point `base_url` at `https://github.example.com/`; use the API root such as `https://github.example.com/api/v3`.
- Do not assume every REST endpoint is wrapped at the same abstraction level. Fall back to `requester.requestJsonAndCheck(...)` when needed.
- Do not assume a valid token has the right scopes or installation permissions. Many `404` and `403` responses on private repos are permission problems, not missing resources.

## Version-Sensitive Notes

- PyPI metadata for `2.6.0` declares `Requires-Python >=3.8`.
- The `stable/` docs root is newer than this guide's pinned package version, so examples there may reflect later releases unless you switch to `https://pygithub.readthedocs.io/en/v2.6.0/`.
- The official `2.6.0` changelog says repository traffic views and clones were reworked: instead of dict-like access, PyGithub now returns objects with `.timestamp`, `.count`, and `.uniques` attributes.
- Inference from official sources: the newer examples page still shows dict-style traffic access (`views['count']` and `views['views']`). For `2.6.0`, trust the changelog and use object attributes instead.
- If you are migrating old code, verify auth construction, pagination behavior, and any direct attribute access copied from old blog posts against the current API reference for `Github`, `Auth`, and the object you are using.

Example for the traffic change:

```python
views = repo.get_views_traffic()
print(views.count)
print(views.views[0].timestamp)
```

## Official Sources

- Docs root: `https://pygithub.readthedocs.io/en/stable/`
- Version-pinned introduction: `https://pygithub.readthedocs.io/en/v2.6.0/introduction.html`
- Version-pinned main class docs: `https://pygithub.readthedocs.io/en/v2.6.0/github.html`
- Utilities docs: `https://pygithub.readthedocs.io/en/latest/utilities.html`
- Examples page: `https://pygithub.readthedocs.io/en/latest/examples/MainClass.html`
- Changelog: `https://pygithub.readthedocs.io/en/v2.6.0/changes.html`
- Repository README: `https://raw.githubusercontent.com/PyGithub/PyGithub/main/README.md`
- Repository: `https://github.com/PyGithub/PyGithub`
- PyPI project: `https://pypi.org/project/PyGithub/`
- PyPI release JSON for `2.6.0`: `https://pypi.org/pypi/PyGithub/2.6.0/json`
