Skip to main content

Official Python client for the Createrington Skin API.

Project description

Createrington Skin API - Python client

createrington-skin-api

Official Python client for the Createrington Skin API. Renders Minecraft player skins into named poses and returns PNG bytes. Sync and async clients, fully typed.

pip install createrington-skin-api

Access is invite-only. Request an API key at https://api.createrington.com.

Quickstart

from createrington_skin_api import SkinApiClient

client = SkinApiClient(api_key="sk_...")  # or set SKIN_API_KEY

# Render a known pose for a Minecraft account by UUID.
png = client.render("wave", uuid="069a79f444e94726a5befca90e38aaf5")

# `png` is `bytes` of a PNG image.
with open("notch-waving.png", "wb") as f:
    f.write(png)

Async

import asyncio
from createrington_skin_api import AsyncSkinApiClient


async def main() -> None:
    async with AsyncSkinApiClient(api_key="sk_...") as client:
        png = await client.render("wave", username="Notch", slim=True)
        with open("notch-waving.png", "wb") as f:
            f.write(png)


asyncio.run(main())

Client

SkinApiClient(
    api_key=None,          # required; falls back to the SKIN_API_KEY env var
    base_url="https://api.createrington.com",
    timeout=30.0,          # seconds
    retries=2,             # retries 429/502/503/504 and network errors
    user_agent="createrington-skin-api",
)

AsyncSkinApiClient takes the same arguments. Both are usable as context managers (with / async with) and expose close() / aclose() for explicit cleanup of the underlying connection pool.

render

client.render(
    pose,                  # a pose name (e.g. "wave"), or any pose string
    *,
    # exactly one skin source:
    uuid=None,             # Mojang UUID, resolved server-side
    username=None,         # Mojang username, resolved server-side
    skin_url=None,         # public URL to a 64x64 PNG
    skin_base64=None,      # base64-encoded 64x64 PNG (data URL prefix optional)
    png=None,              # raw 64x64 PNG bytes, sent as multipart/form-data
    # options:
    slim=None,             # override slim/Alex arm geometry; default uses skin metadata
    outline=False,         # draw an outline around the skin; default off
    width=None,            # default 400 (64..2048)
    height=None,           # default 600 (64..2048)
) -> bytes

Exactly one skin source must be supplied; passing none or more than one raises ValueError.

Poses exposes every pose known to the SDK at publish time as a named constant, so you can reference one by name instead of a bare string:

from createrington_skin_api import Poses

png = client.render(Poses.wave, uuid="069a79f444e94726a5befca90e38aaf5")

pose accepts any string, so server-side poses added after this release work without an SDK upgrade; fetch GET /v1/poses directly if you need the live catalogue with descriptions.

random_pose() returns a uniformly random known pose name:

from createrington_skin_api import random_pose

png = client.render(random_pose(), uuid="069a79f444e94726a5befca90e38aaf5")

avatar

client.avatar(
    *,
    # exactly one skin source (same as render):
    uuid=None,             # Mojang UUID, resolved server-side
    username=None,         # Mojang username, resolved server-side
    skin_url=None,         # public URL to a 64x64 PNG
    skin_base64=None,      # base64-encoded 64x64 PNG (data URL prefix optional)
    png=None,              # raw 64x64 PNG bytes, sent as multipart/form-data
    # options:
    size=None,             # output edge length in px; default 64 (8..512), square
    overlay=None,          # composite the hat layer; on by default
) -> bytes

Returns a flat 2D front-view avatar: a square PNG of the skin's face with the hat layer composited on top. Exactly one skin source must be supplied, the same way as render; passing none or more than one raises ValueError. overlay is on by default and the request omits the parameter unless you pass overlay=False.

png = client.avatar(uuid="069a79f444e94726a5befca90e38aaf5", size=128)

The async client exposes await client.avatar(...) with the same arguments.

resolve

client.resolve(
    *,
    # exactly one identifier:
    uuid=None,             # player UUID, dashed or compact
    username=None,         # Minecraft username, case-insensitive
) -> ResolvedPlayer

Resolves a player identity in either direction: pass uuid to get the current username, or username to get the UUID. Exactly one identifier must be supplied; passing none or both raises ValueError. Returns a ResolvedPlayer dataclass: uuid is always the canonical dashed lowercase form and username carries the canonical casing (None only when a degraded fallback provider could not supply the name). An unknown player raises SkinApiError with code == "not_found".

player = client.resolve(username="Notch")
print(player.uuid)      # "069a79f4-44e9-4726-a5be-fca90e38aaf5"
print(player.username)  # "Notch"

Lookups share the server's resolution cache, so a recent name change can take up to a day to appear. Resolutions do not count toward the image volume quota.

The async client exposes await client.resolve(...) with the same arguments.

Errors

Every non-2xx response (and network/timeout failures) raises SkinApiError:

from createrington_skin_api import SkinApiError

try:
    client.render("wave", uuid="bad-uuid")
except SkinApiError as err:
    print(err.code, err.status, err)
    if err.code == "rate_limited" and err.retry_after_ms:
        ...  # back off and retry

err.code is one of "bad_request", "unauthorized", "forbidden", "not_found", "conflict", "unsupported_media_type", "rate_limited", "internal", "render_failed", "upstream_unavailable", "timeout", "aborted", "network_error", "unknown". err.status is the HTTP status (or 0 for network/timeout failures). err.retry_after_ms is populated on 429 responses when the server reports it.

The client retries 429, 502, 503, 504, and network errors up to retries times with exponential backoff; 429 responses honour the server's retryAfterMs when present.

Building

pip install -e ".[dev]"
pytest
mypy

_poses.py is generated from the published OpenAPI document (fetched live, not committed):

python scripts/generate_poses.py

render accepts any pose string, so a new server-side pose works without an SDK change; Poses and KNOWN_POSES only provide names known at build time.

Contributing

Issues and pull requests are welcome. By submitting a contribution you agree it is licensed under the project's Apache-2.0 terms (section 5 of the license); no separate CLA is required.

License

Apache-2.0. See LICENSE.

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

createrington_skin_api-2.6.0.tar.gz (20.6 kB view details)

Uploaded Source

Built Distribution

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

createrington_skin_api-2.6.0-py3-none-any.whl (20.0 kB view details)

Uploaded Python 3

File details

Details for the file createrington_skin_api-2.6.0.tar.gz.

File metadata

  • Download URL: createrington_skin_api-2.6.0.tar.gz
  • Upload date:
  • Size: 20.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.13

File hashes

Hashes for createrington_skin_api-2.6.0.tar.gz
Algorithm Hash digest
SHA256 29b54495a02c242a68376dfccff560e6ecb1de75a59536f2de8b69097c2a2321
MD5 e0aec5418636e54cfb6cb8705788f964
BLAKE2b-256 dd68adcd2bb8a14606fd6af4ec5d173fbcad02323149e588edcb66095c3f8ca7

See more details on using hashes here.

File details

Details for the file createrington_skin_api-2.6.0-py3-none-any.whl.

File metadata

File hashes

Hashes for createrington_skin_api-2.6.0-py3-none-any.whl
Algorithm Hash digest
SHA256 204e7ee5f99de7bafef83d27b0ce8bc32a0d713533602959eb915a9eeff0b701
MD5 4b1c0a6b906e6c4d621c8f4fe34351f9
BLAKE2b-256 b3856d0f93eef96cb4061e3962ee128ee37e80a099565f273cf0b5bbc3fb1dcd

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