gixenpy
Unofficial Python client for Gixen.com (eBay sniping)
See usage examples »
Report a bug
·
Request a feature
Table of Contents
About The Project
Gixen used to offer a public API for scheduling
snipes (last-second eBay bids); that API is now restricted to regular
users. gixenpy solves that by automating Gixen's web form with requests,
just like a browser with JavaScript disabled would — without depending on an
API that's no longer available.
Not a Gixen product, not affiliated with Gixen.com. Checked against their terms of use and FAQ: they don't prohibit automated access, but use it at your own risk — Gixen may block traffic it doesn't recognize at its discretion.
What you can do with it:
- Schedule (
add_snipe), list (list_snipes), edit (update_snipe), delete (delete_snipe) and purge ended snipes (purge_completed). - Read and change your account's settings (
get_settings/update_settings), search the ended-snipes history (get_history), import snipes from a CSV (import_csv) or from your eBay Watchlist (import_watchlist), refresh current prices (refresh_prices) and log out (logout). - Persistent session: the login session (cookies) is stored to disk and reused, so Gixen doesn't kick your browser out on every run and each action skips the login round-trip.
- Bid, offset (seconds before the close) and bid group, all configurable; in
update_snipeeach one is independent and optional (whatever isn't passed is kept as-is). - Tell active, won and lost snipes apart (
Snipe.status), not just active-vs-ended. - Dynamically locate Gixen's forms by parsing the HTML, instead of assuming fixed field names: if Gixen changes their site, it keeps working as long as the form structure doesn't change too much.
- Dry-run mode (the default for
add_snipeunless told otherwise): sends nothing, just reports what it would send. - A full CLI:
gixenpy list/add/edit/remove/purge/group/history/settings/logout/refresh.
Built With
Getting Started
Prerequisites
- Python 3.10 or newer
- A Gixen account (credentials are Gixen's, not eBay's)
Installation
pip install gixenpy
Or straight from GitHub, for the latest unreleased changes:
pip install git+https://github.com/figurophobia/gixenpy.git
For development (with tests):
git clone https://github.com/figurophobia/gixenpy.git
cd gixenpy
pip install -e ".[dev]"
Usage
As a library
from gixenpy import GixenClient
client = GixenClient(username="your_gixen_username", password="your_password", dry_run=True)
# Schedule a snipe (dry_run=True by default: doesn't bid for real).
result = client.add_snipe(item_id="123456789012", max_bid=42.50)
print(result.message)
# When you want to bid for real:
result = client.add_snipe(item_id="123456789012", max_bid=42.50, dry_run=False)
# Manage existing snipes.
for snipe in client.list_snipes():
print(snipe.item_id, snipe.max_bid, snipe.status) # "active" | "won" | "lost" | "ended" | "unknown"
client.update_snipe(item_id="123456789012", new_max=55)
client.delete_snipe(item_id="123456789012")
# Offset (seconds before the close) and bid group, optional:
client.add_snipe(item_id="123456789012", max_bid=42.50, offset=9, group=1, dry_run=False)
client.update_snipe(item_id="123456789012", offset=12) # change only the offset
client.update_snipe(item_id="123456789012", group=2) # change only the group
client.purge_completed() # remove already-ended snipes from the history
# Settings & history (Gixen's native pages, read/written directly):
settings = client.get_settings() # → Settings(country, ebay_site, default_offset, ...)
client.update_settings(default_offset=5) # change one or more preferences
history = client.get_history(keyword="Sony") # search ended snipes by title
client.refresh_prices() # refresh current bids on active snipes
client.logout() # logout server-side + clear stored session
The session (cookies) is persisted by default to
~/.config/gixenpy/session.json and reused: Gixen only allows one session
per account, so gixenpy won't kick your browser out. Change the file with
session_path= or the GIXEN_SESSION_PATH environment variable; pass
session_path=None to disable persistence.
Credentials are your Gixen account's (not eBay's). Never logged or printed.
As a CLI
export GIXEN_USERNAME=your_username
export GIXEN_PASSWORD=your_password
# or create a .env with those two lines (see .env.example)
gixenpy --help # list of commands
gixenpy --version
gixenpy list # active and ended snipes
gixenpy add 123456789012 42.50 # schedules a snipe FOR REAL
gixenpy add 123456789012 42.50 --offset 9 --group 1 # with offset/group
gixenpy add 123456789012 42.50 --dry-run # just shows what would be sent
gixenpy edit 123456789012 55 # change the max bid
gixenpy edit 123456789012 --offset 12 # change only the offset (keeps the bid)
gixenpy edit 123456789012 --group 2 # change only the group
gixenpy remove 123456789012 # delete the snipe
gixenpy purge # purge ended snipes from the history
gixenpy group 3 123456789012 987654321098 # assign group 3 to several items
gixenpy history # recent ended snipes
gixenpy history Sony # search ended snipes by title keyword
gixenpy settings # show current account settings
gixenpy refresh # refresh current prices on active snipes
gixenpy logout # log out and clear the stored session
Every command exits with code 0 if Gixen confirmed the operation, or 1
if it failed/errored (message on stderr, prefixed with ERROR:).
Security
- A small, fixed number of requests per action (1 GET + 1 POST), no aggressive polling.
- Reuses the existing session instead of relogging on every action (avoiding unnecessarily kicking out other sessions — Gixen only allows one active session per account).
- The max bid amount is always decided by whoever calls the library; it never picks a value on its own.
- Any form URL extracted from Gixen's HTML is validated against
gixen.com(and HTTPS only) before sending anything; a tampered response can't make the client send the payload to a different host. - Configurable connect/read timeouts (
GixenClient(timeout=...), default(5, 25)seconds) to fail fast on network issues. - A single retry with backoff (
GixenClient(retry_backoff=...), 2 seconds by default) if Gixen accepts a write but doesn't end up applying it — never on an explicit rejection.
Tests
pip install -e ".[dev]"
pytest -q
Neither suite makes any network requests: tests/test_client.py replaces
Gixen's logged-in page with test HTML and verifies form parsing and the
payload built; tests/test_cli.py exercises the CLI with
click.testing.CliRunner, injecting a fake client.
Publishing to PyPI
gixenpy is published on PyPI. New
releases are published automatically: publishing a
GitHub Release triggers
.github/workflows/publish.yml, which
builds the package and uploads it to PyPI using
Trusted Publishing (OIDC —
no API token stored anywhere).
To cut a new release:
- Bump the version in
pyproject.tomlandsrc/gixenpy/__init__.py, updateCHANGELOG.md, commit and push. - Tag it and publish a GitHub Release (e.g.
gh release create v0.3.0). - That's it — the workflow builds and uploads it to PyPI.
Manual publishing still works too, if ever needed:
pip install -e ".[dev]" build twine
python -m build # generates dist/*.tar.gz and dist/*.whl
twine check dist/* # validates the package
twine upload dist/* # requires your own PyPI API token
Roadmap
- Publish
gixenpyon PyPI - Persistent session across processes (sessions persisted to
~/.config/gixenpy/session.jsonand reused automatically) - Account settings (
get_settings/update_settings), ended-snipes history (get_history), CSV/Watchlist import,refresh_prices,logout - Revisit the active/ended status heuristic if Gixen changes the text/order of "Status (main): ..." in their HTML
See the open issues for the full list of proposed features (and known issues).
Contributing
Contributions are welcome. If you have an idea that would make this better, fork the repo and open a pull request, or simply open an issue with the "enhancement" tag.
- Fork the Project
- Create your Feature Branch (
git checkout -b feature/my-feature) - Commit your Changes (
git commit -m 'Add my-feature') - Push to the Branch (
git push origin feature/my-feature) - Open a Pull Request
License
Distributed under the MIT License. See LICENSE for more
information.
Contact
Project issues: github.com/figurophobia/gixenpy/issues
Acknowledgments
- hsukenooi/gixen-cli — another independent implementation of the same problem, used as a reference for several improvements to this library
- Best-README-Template — the template used for this README
- Gixen.com for the sniping service itself
Metadata
Release files for gixenpy 0.5.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| gixenpy-0.5.0.tar.gz | 40.5 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| gixenpy-0.5.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 67.8 kB
Release files / gixenpy-0.5.0.tar.gz
| Download URL | gixenpy-0.5.0.tar.gz |
|---|---|
| Size | 40.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
144f44a833db80f23ca8e6ca7993592c6104246d3f28b020f6d5806f5696dec3
|
|
BLAKE2b-256 checksum How to use checksums |
b5f51e1537baba176e42a03eabc2290d328e3b4ecea51d8cbd7a33eb1ab953c1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 6, 2026.
Transparency logRelease files / gixenpy-0.5.0-py3-none-any.whl
| Download URL | gixenpy-0.5.0-py3-none-any.whl |
|---|---|
| Size | 27.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
cc3ac35181ca6900717323e9f5d53c5d1c399240f028b854d67095a060ae8656
|
|
BLAKE2b-256 checksum How to use checksums |
f0a77c998cc8fac0af8a4969dbfba8bd64a0984f44e42143c109726c8d09b390
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 6, 2026.
Transparency log