Skip to content

Query Builder

SpaceTrackQuery provides a fluent builder API for constructing Space-Track.org API queries. Each builder method returns a new query instance, allowing method chaining. Call build() to produce the URL path string that the client appends to the base URL.

For the complete API reference, see the SpaceTrackQuery Reference.

Basic Queries

Create a query by specifying the request class. The default controller is selected automatically based on the class -- GP and SATCAT use BasicSpaceData, while CDMPublic uses ExpandedSpaceData. Add filters with the filter() method using Space-Track field names.

import brahe as bh

# Build a GP query for the ISS by NORAD catalog ID
query = bh.SpaceTrackQuery(bh.RequestClass.GP).filter("NORAD_CAT_ID", "25544")

url_path = query.build()
print(f"GP query URL path:\n  {url_path}")

# Build a SATCAT query for US-owned objects
query = bh.SpaceTrackQuery(bh.RequestClass.SATCAT).filter("COUNTRY", "US")

url_path = query.build()
print(f"\nSATCAT query URL path:\n  {url_path}")

# The default controller is inferred from the request class
query = bh.SpaceTrackQuery(bh.RequestClass.CDM_PUBLIC)
url_path = query.build()
print(f"\nCDM query URL path (uses expandedspacedata controller):\n  {url_path}")
use brahe as bh;
use bh::spacetrack::{SpaceTrackQuery, RequestClass};

fn main() {
    // Build a GP query for the ISS by NORAD catalog ID
    let query = SpaceTrackQuery::new(RequestClass::GP)
        .filter("NORAD_CAT_ID", "25544");

    let url_path = query.build();
    println!("GP query URL path:\n  {}", url_path);

    // Build a SATCAT query for US-owned objects
    let query = SpaceTrackQuery::new(RequestClass::SATCAT)
        .filter("COUNTRY", "US");

    let url_path = query.build();
    println!("\nSATCAT query URL path:\n  {}", url_path);

    // The default controller is inferred from the request class
    let query = SpaceTrackQuery::new(RequestClass::CDMPublic);
    let url_path = query.build();
    println!("\nCDM query URL path (uses expandedspacedata controller):\n  {}", url_path);
}
Output
1
2
3
4
5
6
7
8
GP query URL path:
  /basicspacedata/query/class/gp/NORAD_CAT_ID/25544/format/json

SATCAT query URL path:
  /basicspacedata/query/class/satcat/COUNTRY/US/format/json

CDM query URL path (uses expandedspacedata controller):
  /basicspacedata/query/class/cdm_public/format/json
1
2
3
4
5
6
7
8
GP query URL path:
  /basicspacedata/query/class/gp/NORAD_CAT_ID/25544/format/json

SATCAT query URL path:
  /basicspacedata/query/class/satcat/COUNTRY/US/format/json

CDM query URL path (uses expandedspacedata controller):
  /basicspacedata/query/class/cdm_public/format/json

Filters and Operators

The operators module provides functions that generate operator-prefixed strings for filter values. These compose naturally -- greater_than(now_offset(-7)) nests the time offset inside the comparison operator.

import brahe as bh
from brahe.spacetrack import operators as op

# Filter by NORAD ID range using inclusive_range
query = bh.SpaceTrackQuery(bh.RequestClass.GP).filter(
    "NORAD_CAT_ID", op.inclusive_range("25544", "25600")
)
print(f"Range filter:\n  {query.build()}")

# Filter for objects with low eccentricity using less_than
query = (
    bh.SpaceTrackQuery(bh.RequestClass.GP)
    .filter("ECCENTRICITY", op.less_than("0.01"))
    .filter("OBJECT_TYPE", "PAYLOAD")
)
print(f"\nMultiple filters:\n  {query.build()}")

# Filter for recently launched objects using greater_than + now_offset
query = bh.SpaceTrackQuery(bh.RequestClass.SATCAT).filter(
    "LAUNCH", op.greater_than(op.now_offset(-30))
)
print(f"\nRecent launches (last 30 days):\n  {query.build()}")

# Search by name pattern using like
query = bh.SpaceTrackQuery(bh.RequestClass.SATCAT).filter(
    "SATNAME", op.like("STARLINK")
)
print(f"\nName pattern match:\n  {query.build()}")

# Filter for multiple NORAD IDs using or_list
query = bh.SpaceTrackQuery(bh.RequestClass.GP).filter(
    "NORAD_CAT_ID", op.or_list(["25544", "48274", "54216"])
)
print(f"\nMultiple IDs:\n  {query.build()}")
use brahe as bh;
use bh::spacetrack::{SpaceTrackQuery, RequestClass};
use bh::spacetrack::operators;

fn main() {
    // Filter by NORAD ID range using inclusive_range
    let query = SpaceTrackQuery::new(RequestClass::GP)
        .filter("NORAD_CAT_ID", &operators::inclusive_range("25544", "25600"));
    println!("Range filter:\n  {}", query.build());

    // Filter for objects with low eccentricity using less_than
    let query = SpaceTrackQuery::new(RequestClass::GP)
        .filter("ECCENTRICITY", &operators::less_than("0.01"))
        .filter("OBJECT_TYPE", "PAYLOAD");
    println!("\nMultiple filters:\n  {}", query.build());

    // Filter for recently launched objects using greater_than + now_offset
    let query = SpaceTrackQuery::new(RequestClass::SATCAT)
        .filter("LAUNCH", &operators::greater_than(operators::now_offset(-30)));
    println!("\nRecent launches (last 30 days):\n  {}", query.build());

    // Search by name pattern using like
    let query = SpaceTrackQuery::new(RequestClass::SATCAT)
        .filter("SATNAME", &operators::like("STARLINK"));
    println!("\nName pattern match:\n  {}", query.build());

    // Filter for multiple NORAD IDs using or_list
    let query = SpaceTrackQuery::new(RequestClass::GP)
        .filter("NORAD_CAT_ID", &operators::or_list(&["25544", "48274", "54216"]));
    println!("\nMultiple IDs:\n  {}", query.build());
}
Output
Range filter:
  /basicspacedata/query/class/gp/NORAD_CAT_ID/25544--25600/format/json

Multiple filters:
  /basicspacedata/query/class/gp/ECCENTRICITY/%3C0.01/OBJECT_TYPE/PAYLOAD/format/json

Recent launches (last 30 days):
  /basicspacedata/query/class/satcat/LAUNCH/%3Enow-30/format/json

Name pattern match:
  /basicspacedata/query/class/satcat/SATNAME/~~STARLINK/format/json

Multiple IDs:
  /basicspacedata/query/class/gp/NORAD_CAT_ID/25544,48274,54216/format/json
Range filter:
  /basicspacedata/query/class/gp/NORAD_CAT_ID/25544--25600/format/json

Multiple filters:
  /basicspacedata/query/class/gp/ECCENTRICITY/%3C0.01/OBJECT_TYPE/PAYLOAD/format/json

Recent launches (last 30 days):
  /basicspacedata/query/class/satcat/LAUNCH/%3Enow-30/format/json

Name pattern match:
  /basicspacedata/query/class/satcat/SATNAME/~~STARLINK/format/json

Multiple IDs:
  /basicspacedata/query/class/gp/NORAD_CAT_ID/25544,48274,54216/format/json

Operator Composition

Operators are string-generating functions. You can compose them by nesting:

  • greater_than(now_offset(-7)) produces ">now-7" (epoch after 7 days ago)
  • inclusive_range(now_offset(-30), now()) produces "now-30--now" (within last 30 days)

Ordering, Limits, and Options

Control result ordering, pagination, and field selection. Multiple order_by calls are cumulative -- results are sorted by the first field, then by subsequent fields for ties.

import brahe as bh

# Order results by epoch descending and limit to 5 records
query = (
    bh.SpaceTrackQuery(bh.RequestClass.GP)
    .filter("NORAD_CAT_ID", "25544")
    .order_by("EPOCH", bh.SortOrder.DESC)
    .limit(5)
)
print(f"Ordered and limited:\n  {query.build()}")

# Use limit with offset for pagination
query = (
    bh.SpaceTrackQuery(bh.RequestClass.GP)
    .filter("OBJECT_TYPE", "PAYLOAD")
    .order_by("NORAD_CAT_ID", bh.SortOrder.ASC)
    .limit_offset(10, 20)
)
print(f"\nPaginated results:\n  {query.build()}")

# Select specific fields with predicates_filter
query = (
    bh.SpaceTrackQuery(bh.RequestClass.GP)
    .filter("NORAD_CAT_ID", "25544")
    .predicates_filter(["OBJECT_NAME", "EPOCH", "INCLINATION", "PERIOD"])
)
print(f"\nFiltered fields:\n  {query.build()}")

# Enable metadata and distinct results
query = (
    bh.SpaceTrackQuery(bh.RequestClass.SATCAT)
    .filter("COUNTRY", "US")
    .distinct(True)
    .metadata(True)
)
print(f"\nDistinct with metadata:\n  {query.build()}")
use brahe as bh;
use bh::spacetrack::{SpaceTrackQuery, RequestClass, SortOrder};

fn main() {
    // Order results by epoch descending and limit to 5 records
    let query = SpaceTrackQuery::new(RequestClass::GP)
        .filter("NORAD_CAT_ID", "25544")
        .order_by("EPOCH", SortOrder::Desc)
        .limit(5);
    println!("Ordered and limited:\n  {}", query.build());

    // Use limit with offset for pagination
    let query = SpaceTrackQuery::new(RequestClass::GP)
        .filter("OBJECT_TYPE", "PAYLOAD")
        .order_by("NORAD_CAT_ID", SortOrder::Asc)
        .limit_offset(10, 20);
    println!("\nPaginated results:\n  {}", query.build());

    // Select specific fields with predicates_filter
    let query = SpaceTrackQuery::new(RequestClass::GP)
        .filter("NORAD_CAT_ID", "25544")
        .predicates_filter(&["OBJECT_NAME", "EPOCH", "INCLINATION", "PERIOD"]);
    println!("\nFiltered fields:\n  {}", query.build());

    // Enable metadata and distinct results
    let query = SpaceTrackQuery::new(RequestClass::SATCAT)
        .filter("COUNTRY", "US")
        .distinct(true)
        .metadata(true);
    println!("\nDistinct with metadata:\n  {}", query.build());
}
Output
Ordered and limited:
  /basicspacedata/query/class/gp/NORAD_CAT_ID/25544/orderby/EPOCH%20desc/limit/5/format/json

Paginated results:
  /basicspacedata/query/class/gp/OBJECT_TYPE/PAYLOAD/orderby/NORAD_CAT_ID%20asc/limit/10,20/format/json

Filtered fields:
  /basicspacedata/query/class/gp/NORAD_CAT_ID/25544/predicates/OBJECT_NAME,EPOCH,INCLINATION,PERIOD/format/json

Distinct with metadata:
  /basicspacedata/query/class/satcat/COUNTRY/US/metadata/true/distinct/true/format/json
Ordered and limited:
  /basicspacedata/query/class/gp/NORAD_CAT_ID/25544/orderby/EPOCH%20desc/limit/5/format/json

Paginated results:
  /basicspacedata/query/class/gp/OBJECT_TYPE/PAYLOAD/orderby/NORAD_CAT_ID%20asc/limit/10,20/format/json

Filtered fields:
  /basicspacedata/query/class/gp/NORAD_CAT_ID/25544/predicates/OBJECT_NAME,EPOCH,INCLINATION,PERIOD/format/json

Distinct with metadata:
  /basicspacedata/query/class/satcat/COUNTRY/US/metadata/true/distinct/true/format/json

Output Formats

The default output format is JSON, which works with query_json(), query_gp(), and query_satcat(). Other formats like TLE, CSV, and KVN are useful with query_raw() for direct text output.

import brahe as bh

# Default format is JSON
query = bh.SpaceTrackQuery(bh.RequestClass.GP).filter("NORAD_CAT_ID", "25544")
print(f"Default (JSON):\n  {query.build()}")

# Request TLE format for direct TLE text output
query = (
    bh.SpaceTrackQuery(bh.RequestClass.GP)
    .filter("NORAD_CAT_ID", "25544")
    .format(bh.OutputFormat.TLE)
)
print(f"\nTLE format:\n  {query.build()}")

# Request CSV format for spreadsheet-compatible output
query = (
    bh.SpaceTrackQuery(bh.RequestClass.SATCAT)
    .filter("COUNTRY", "US")
    .limit(10)
    .format(bh.OutputFormat.CSV)
)
print(f"\nCSV format:\n  {query.build()}")

# Request KVN (CCSDS Keyword-Value Notation) format
query = (
    bh.SpaceTrackQuery(bh.RequestClass.GP)
    .filter("NORAD_CAT_ID", "25544")
    .format(bh.OutputFormat.KVN)
)
print(f"\nKVN format:\n  {query.build()}")
use brahe as bh;
use bh::spacetrack::{SpaceTrackQuery, RequestClass, OutputFormat};

fn main() {
    // Default format is JSON
    let query = SpaceTrackQuery::new(RequestClass::GP)
        .filter("NORAD_CAT_ID", "25544");
    println!("Default (JSON):\n  {}", query.build());

    // Request TLE format for direct TLE text output
    let query = SpaceTrackQuery::new(RequestClass::GP)
        .filter("NORAD_CAT_ID", "25544")
        .format(OutputFormat::TLE);
    println!("\nTLE format:\n  {}", query.build());

    // Request CSV format for spreadsheet-compatible output
    let query = SpaceTrackQuery::new(RequestClass::SATCAT)
        .filter("COUNTRY", "US")
        .limit(10)
        .format(OutputFormat::CSV);
    println!("\nCSV format:\n  {}", query.build());

    // Request KVN (CCSDS Keyword-Value Notation) format
    let query = SpaceTrackQuery::new(RequestClass::GP)
        .filter("NORAD_CAT_ID", "25544")
        .format(OutputFormat::KVN);
    println!("\nKVN format:\n  {}", query.build());
}
Output
Default (JSON):
  /basicspacedata/query/class/gp/NORAD_CAT_ID/25544/format/json

TLE format:
  /basicspacedata/query/class/gp/NORAD_CAT_ID/25544/format/tle

CSV format:
  /basicspacedata/query/class/satcat/COUNTRY/US/limit/10/format/csv

KVN format:
  /basicspacedata/query/class/gp/NORAD_CAT_ID/25544/format/kvn
Default (JSON):
  /basicspacedata/query/class/gp/NORAD_CAT_ID/25544/format/json

TLE format:
  /basicspacedata/query/class/gp/NORAD_CAT_ID/25544/format/tle

CSV format:
  /basicspacedata/query/class/satcat/COUNTRY/US/limit/10/format/csv

KVN format:
  /basicspacedata/query/class/gp/NORAD_CAT_ID/25544/format/kvn

Format and Query Method Compatibility

The typed query methods (query_gp(), query_satcat(), query_json()) require JSON format. If you set a non-JSON format, use query_raw() to get the raw response string.


See Also