Skip to main content

Use the OpenAI Python SDK with your own ChatGPT subscription

Project description

login-with-chatgpt

Use the official openai Python SDK with your own ChatGPT subscription. login_with_chatgpt.OpenAI() returns a real openai.OpenAI client while replacing API-key authentication and transport with ChatGPT OAuth and the Codex backend.

[!WARNING] This package uses private, undocumented ChatGPT Codex endpoints. It is not the public OpenAI API, has no compatibility or availability guarantee, and may stop working when the upstream protocol changes. Requests consume the signed-in user's ChatGPT plan and limits, not OpenAI API credits.

Requirements

  • Python 3.11 or newer
  • A ChatGPT account with Codex access
  • An operating-system keyring supported by keyring

Codex CLI is not required at runtime. Its source and behavior are protocol references only; no Codex checkout is imported or included in distributions.

Install and sign in

uvx login-with-chatgpt login
uv add login-with-chatgpt

Browser PKCE is the default. For SSH, containers, and other headless environments:

uvx login-with-chatgpt login --device

Credentials are stored in the operating-system keyring. The SDK does not fall back to a plaintext token file. Access tokens are refreshed automatically before expiry and once after an HTTP 401 response.

Confirm the active account and available conversation models:

uvx login-with-chatgpt status
uvx login-with-chatgpt models
uvx login-with-chatgpt doctor

Quick start

from login_with_chatgpt import OpenAI

client = OpenAI()
response = client.responses.create(
    model="gpt-5.6-sol",
    input="Explain Python descriptors in three sentences.",
)
print(response.output_text)
client.close()

OpenAI() returns an upstream openai.OpenAI object, so upstream response models, exceptions, Pydantic parsing, streaming helpers, and function-tool helpers remain available on the supported endpoints. Async applications use AsyncOpenAI().

from login_with_chatgpt import AsyncOpenAI


async def main() -> None:
    client = AsyncOpenAI()
    try:
        response = await client.responses.create(
            model="gpt-5.6-sol",
            input="Reply with only: async ok",
        )
        print(response.output_text)
    finally:
        await client.close()

Supported API surface

Python surface Codex endpoint Status
client.responses.create() POST /responses Supported
client.responses.parse() POST /responses Supported
client.responses.stream() POST /responses Supported
client.images.generate() POST /images/generations Supported, non-streaming
client.images.edit() POST /images/edits Supported, non-streaming
ChatGPTAccount().list_models() GET /models Supported
Other upstream resources Other endpoints Rejected before network access

The transport only allows the ChatGPT Codex origin and the methods and paths in this table. In particular, use ChatGPTAccount().list_models() instead of client.models.list().

Responses

Verified Responses features are:

  • text input and output
  • synchronous and asynchronous SSE streaming
  • Pydantic structured output through responses.parse()
  • function tools and parsed function arguments
  • image URL and image data URL input
  • function-result continuation
  • stateless multi-turn history replay

Structured output

from pydantic import BaseModel

from login_with_chatgpt import OpenAI


class Answer(BaseModel):
    summary: str
    points: list[str]


client = OpenAI()
response = client.responses.parse(
    model="gpt-5.6-sol",
    input="Summarize OAuth PKCE.",
    text_format=Answer,
)
print(response.output_parsed)
client.close()

Streaming

from login_with_chatgpt import OpenAI

client = OpenAI()
with client.responses.stream(
    model="gpt-5.6-sol",
    input="Write one short sentence.",
) as stream:
    for event in stream:
        if event.type == "response.output_text.delta":
            print(event.delta, end="", flush=True)
client.close()

The Codex Responses endpoint is treated as stateless. The following are rejected rather than silently removed or ignored:

  • store=True
  • previous_response_id and conversation
  • background responses
  • max_output_tokens and max_completion_tokens
  • hosted tools other than function tools
  • file and audio inputs

GPT Image 2

Image generation and editing use the standalone ChatGPT Codex image endpoints. The return value remains the upstream openai.types.ImagesResponse model.

Generate an image

import base64
from pathlib import Path

from login_with_chatgpt import OpenAI

client = OpenAI()
result = client.images.generate(
    model="gpt-image-2",
    prompt="A quiet Tokyo street after rain",
    background="opaque",
    quality="low",
    size="1024x1024",
)

assert result.data and result.data[0].b64_json
Path("tokyo.png").write_bytes(base64.b64decode(result.data[0].b64_json))
client.close()

Edit one or more images

The normal openai-python file interface is preserved. PNG, JPEG, and WebP files are converted to the data URL JSON format expected by Codex.

import base64
from pathlib import Path

from login_with_chatgpt import OpenAI

client = OpenAI()
with Path("source.png").open("rb") as source:
    result = client.images.edit(
        model="gpt-image-2",
        image=source,
        prompt="Change the lighting to late afternoon",
        quality="medium",
        size="1024x1024",
    )

assert result.data and result.data[0].b64_json
Path("edited.png").write_bytes(base64.b64decode(result.data[0].b64_json))
client.close()

The verified image request controls are background, n, quality, size, and response_format="b64_json". Editing accepts up to five source images, with each source limited to 50 MiB.

Image streaming, masks, transparent gpt-image-2 backgrounds, other image models, and unverified output controls are rejected before network access. This includes output_format, output_compression, partial_images, input_fidelity, moderation, style, and user.

login-with-chatgpt models intentionally lists conversation models only. gpt-image-2 is selected directly on client.images and is not inserted into the server's conversation-model catalog.

Profiles and CLI

login-with-chatgpt --profile work login
login-with-chatgpt profiles
login-with-chatgpt use work
login-with-chatgpt status
login-with-chatgpt models
login-with-chatgpt doctor
login-with-chatgpt logout

Profile precedence is:

  1. Explicit --profile or Python profile= argument
  2. LOGIN_WITH_CHATGPT_PROFILE
  3. Active profile selected by login-with-chatgpt use
  4. default

Python code can select a profile without changing the CLI default:

from login_with_chatgpt import OpenAI

work = OpenAI(profile="work")
personal = OpenAI(profile="personal")

The library does not rotate profiles automatically. Applications that need account selection or rotation should implement that policy explicitly.

Protocol compatibility

The package version and tested Codex protocol version are independent:

login-with-chatgpt Tested Codex protocol openai-python
0.1.1 0.144.1 >=2.45.0,<3

The tested protocol version is the default. For an urgent compatibility override, use either the environment or the Python constructor:

$env:LOGIN_WITH_CHATGPT_CLIENT_VERSION = "0.145.0"
login-with-chatgpt doctor
from login_with_chatgpt import OpenAI

client = OpenAI(client_version="0.145.0")

doctor reports the effective protocol version and, when installed, the local Codex CLI version. Codex CLI detection is diagnostic only and never changes the SDK version automatically.

Development

uv sync --dev
uv run ruff check .
uv run pyright
uv run pytest
uv build

Real-account contract checks are opt-in because they consume subscription usage.

Responses contract test:

$env:LOGIN_WITH_CHATGPT_LIVE_MODEL = "gpt-5.6-sol"
uv run pytest tests/test_live.py -m live

Image generation and edit contract test, which creates two images:

$env:LOGIN_WITH_CHATGPT_LIVE_IMAGE_MODEL = "gpt-image-2"
uv run pytest tests/test_live_images.py -m live

On POSIX shells, use export NAME=value instead of PowerShell's $env:NAME = "value" syntax. Live tests use the currently active credential profile and are never run by CI.

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

login_with_chatgpt-0.1.2.tar.gz (76.0 kB view details)

Uploaded Source

Built Distribution

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

login_with_chatgpt-0.1.2-py3-none-any.whl (35.3 kB view details)

Uploaded Python 3

File details

Details for the file login_with_chatgpt-0.1.2.tar.gz.

File metadata

  • Download URL: login_with_chatgpt-0.1.2.tar.gz
  • Upload date:
  • Size: 76.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.7.12

File hashes

Hashes for login_with_chatgpt-0.1.2.tar.gz
Algorithm Hash digest
SHA256 a1b7f852e1e3623d17b6c657ca2095e5194379fd91f28badb0175117319021d1
MD5 7c9bd3bc6f1c75cbc077a59e70854edc
BLAKE2b-256 094505a9d229345ac1e9a75ee73dd2d76770f74fb9fca262a4aedaa82625eec6

See more details on using hashes here.

File details

Details for the file login_with_chatgpt-0.1.2-py3-none-any.whl.

File metadata

File hashes

Hashes for login_with_chatgpt-0.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 e9170ddb92cd9a6d6ae3e6a00f7d93af557c3883d4adee7fe7f6ee8cfc32f794
MD5 11444588ad7a9e649022f794f5839a72
BLAKE2b-256 48ccf35305362cca10f687945fcd7f9b9bbc1da8c4fdee3768f5f149ee68c38b

See more details on using hashes here.

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