GMX Guide

Data & developers

Reading time
5 minutes
Last source check
July 26, 2026

Use the GMX API with Python

Python can consume GMX public market data without a wallet or private key. The difficult part is not the HTTP request. It is selecting the intended market, decoding fixed-point values correctly and refusing stale or malformed responses.

The example below reads the official Arbitrum markets/info endpoint, keeps listed perpetual markets, converts funding and borrowing rates and selects the deepest pool for each base symbol. It never signs or submits a transaction.

In this guide
  1. 01Install the small dependency set
  2. 02Fetch and normalize current markets
  3. 03Understand every conversion
  4. 04Interpret signs and separate costs
  5. 05Add freshness and fallback handling
  6. 06Store data without losing precision
  7. 07Keep execution separate from research

Key takeaways

  1. 01Public GMX market data does not require a wallet key.
  2. 02Keep fixed-point integers intact until explicit conversion.
  3. 03Convert annualized rates to hourly values with 8,760 hours.
  4. 04Select duplicate-symbol pools with a documented rule.
  5. 05Separate read-only research from any transaction-signing service.
01

Install the small dependency set

The example uses requests because it provides straightforward timeouts and status handling. Install it in a virtual environment with python -m pip install requests. No unofficial GMX package is required for public REST data.

Keep dependencies narrow for a monitoring job. Add a schema library such as Pydantic if data moves into a database or user-facing service. Pin the dependency version in production and run the job with a recent supported Python release.

02

Fetch and normalize current markets

The code sends an identifiable User-Agent, uses a finite timeout and verifies the top-level response type. It filters on isListed and the /USD market name. It does not filter by trading volume because volume is not a sound substitute for available depth or open interest.

GMX can list more than one pool for the same base asset. The example groups by the name before /USD and retains the market with the largest combined long and short open interest. It then removes selections below a 100,000 dollar combined-open-interest floor so tiny pools do not dominate a public table.

Read-only GMX funding scannerpython
import requests

URL = "https://arbitrum-api.gmxinfra.io/markets/info"
HEADERS = {
    "Accept": "application/json",
    "User-Agent": "my-gmx-research/1.0 (+https://example.com/contact)",
}
OI_FLOOR_USD = 100_000

response = requests.get(URL, headers=HEADERS, timeout=10)
response.raise_for_status()
markets = response.json()
if not isinstance(markets, list):
    raise TypeError("Expected a list of GMX markets")

def usd_1e30(raw: str) -> float:
    return int(raw) / 1e30

def rate_apr_percent(raw: str) -> float:
    return int(raw) / 1e30 * 100

def rate_hourly_percent(raw: str) -> float:
    return int(raw) / 1e30 / 8760 * 100

selected = {}
for market in markets:
    name = str(market.get("name", ""))
    if not market.get("isListed") or "/USD" not in name:
        continue
    base = name.split("/USD", 1)[0]
    long_oi = usd_1e30(market["openInterestLong"])
    short_oi = usd_1e30(market["openInterestShort"])
    total_oi = long_oi + short_oi
    row = {
        "base": base,
        "market": name,
        "market_token": market["marketToken"],
        "open_interest_usd": total_oi,
        "long_funding_apr_pct": rate_apr_percent(market["fundingRateLong"]),
        "long_funding_hourly_pct": rate_hourly_percent(market["fundingRateLong"]),
        "long_borrow_apr_pct": rate_apr_percent(market["borrowingRateLong"]),
    }
    current = selected.get(base)
    if current is None or total_oi > current["open_interest_usd"]:
        selected[base] = row

rows = sorted(
    (row for row in selected.values() if row["open_interest_usd"] >= OI_FLOOR_USD),
    key=lambda row: row["open_interest_usd"],
    reverse=True,
)

for row in rows[:20]:
    print(
        f'{row["base"]:8} OI ${row["open_interest_usd"]:,.0f} '
        f'long funding {row["long_funding_apr_pct"]:+.2f}% APR '
        f'({row["long_funding_hourly_pct"]:+.5f}%/h)'
    )
03

Understand every conversion

Open interest and near-live rate fields in this endpoint use 1e30 scaling. Dividing a funding value by 1e30 returns an annual fraction. A result of 0.12 means 12% APR, not 0.12% and not 12% per hour. The code multiplies by 100 only for the percentage display.

The hourly value divides the annual fraction by 8,760 before multiplying by 100. That is a simple annual-to-hourly display conversion, not a promise that the realized charge will remain constant. Rates move with market state.

04

Interpret signs and separate costs

A positive long funding value means longs pay under the documented convention. A negative long value means longs receive. The short field should be displayed independently because claim factors and collateral accounting can make the two published values look asymmetric.

Borrowing and funding solve different problems. Funding transfers value according to long/short imbalance. Borrowing charges the side with larger open interest under the current model. Keep both columns in stored data rather than adding them into a number called funding.

05

Add freshness and fallback handling

A production script should save retrieval time, source host and a hash or market count. If the endpoint succeeds with no listed markets, fail the run and retain the previous known-good snapshot with a stale label. Never present old data as live.

GMX documents fallback Oracle hosts. Try them only after a timeout, connection error or retryable response from the primary host. Use short bounded retries with jitter. A schema error should alert the operator because repeating the same invalid response across hosts will not repair the parser.

  • Track last successful retrieval and source timestamp separately.
  • Set connect and read timeouts rather than allowing an infinite wait.
  • Reject non-finite converted values and negative open interest.
  • Log marketToken so similarly named pools remain distinguishable.
  • Test with negative rates, zero values and duplicate base assets.
06

Store data without losing precision

For analytics, store the original integer string alongside the normalized decimal. Python integers preserve the raw value, while a binary float can lose precision. Decimal is a better choice when exact downstream arithmetic matters.

Use a composite key containing network, marketToken and observation time. The display symbol alone is not stable enough because different collateral pools can share the same base. If you later join Oracle tickers, normalize addresses to lowercase for matching while preserving a checksummed value for display.

07

Keep execution separate from research

This read-only program needs no secret. If you later build transactions, isolate the signer in another service and begin with simulation. Never paste a private key into a notebook, source file or environment printed by logs.

GMX transaction building involves contracts, acceptable prices, execution fees, network state and keeper execution. Use the official frontend integration documentation and current contract addresses. Public API success is not evidence that a trade transaction will succeed.

Primary sources

These sources were checked on July 26, 2026. Protocol parameters can change.

  1. 01GMX Docs: Integration guide
  2. 02GMX Docs: Markets REST API
  3. 03GMX Docs: Frontend integration
Read our verification methodology →

Referral disclosure

10% off eligible GMX position fees

Code PRO maps to GMX's tier-2 discount on eligible opening and closing position fees. The link is sponsored; the discount and protocol risks are unchanged.

Open GMX

Frequently asked questions

Is there an official GMX Python SDK?

GMX documents APIs, contracts and a TypeScript-oriented SDK surface. Python can call the public REST and GraphQL endpoints directly, but you should verify any third-party Python package before trusting it.

Why divide GMX funding rates by 1e30?

The near-live markets/info funding and borrowing fields are annualized fixed-point values scaled by 1e30. Dividing by 1e30 returns the annual fraction.

Why does the Python example select one pool per symbol?

GMX can list several collateral pools for the same base asset. The example chooses the pool with the greatest combined open interest so a compact symbol table has a transparent rule.

Does the script place GMX trades?

No. It only reads public market data. It contains no wallet connection, signer, private key or transaction submission.

Can I use the output for a backtest?

A single current snapshot is not enough. Use documented historical endpoints, account for endpoint cache intervals, keep original timestamps and model fees, price impact and execution constraints.

Continue learning

Related GMX guides