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}")
# GP query URL path:
#   /basicspacedata/query/class/gp/NORAD_CAT_ID/25544/format/json

# 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}")
# SATCAT query URL path:
#   /basicspacedata/query/class/satcat/COUNTRY/US/format/json

# 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}")
# CDM query URL path (uses expandedspacedata controller):
#   /expandedspacedata/query/class/cdm_public/format/json
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);
    // GP query URL path:
    //   /basicspacedata/query/class/gp/NORAD_CAT_ID/25544/format/json

    // 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);
    // SATCAT query URL path:
    //   /basicspacedata/query/class/satcat/COUNTRY/US/format/json

    // 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);
    // CDM query URL path (uses expandedspacedata controller):
    //   /expandedspacedata/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()}")
# Range filter:
#   /basicspacedata/query/class/gp/NORAD_CAT_ID/25544--25600/format/json

# 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()}")
# Multiple filters:
#   /basicspacedata/query/class/gp/ECCENTRICITY/<0.01/OBJECT_TYPE/PAYLOAD/format/json

# 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()}")
# Recent launches (last 30 days):
#   /basicspacedata/query/class/satcat/LAUNCH/>now-30/format/json

# 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()}")
# Name pattern match:
#   /basicspacedata/query/class/satcat/SATNAME/~~STARLINK/format/json

# 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()}")
# Multiple IDs:
#   /basicspacedata/query/class/gp/NORAD_CAT_ID/25544,48274,54216/format/json
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());
    // Range filter:
    //   /basicspacedata/query/class/gp/NORAD_CAT_ID/25544--25600/format/json

    // 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());
    // Multiple filters:
    //   /basicspacedata/query/class/gp/ECCENTRICITY/<0.01/OBJECT_TYPE/PAYLOAD/format/json

    // 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());
    // Recent launches (last 30 days):
    //   /basicspacedata/query/class/satcat/LAUNCH/>now-30/format/json

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

    // 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());
    // 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()}")
# Ordered and limited:
#   /basicspacedata/query/class/gp/NORAD_CAT_ID/25544/orderby/EPOCH desc/limit/5/format/json

# 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()}")
# Paginated results:
#   /basicspacedata/query/class/gp/OBJECT_TYPE/PAYLOAD/orderby/NORAD_CAT_ID asc/limit/10,20/format/json

# 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()}")
# Filtered fields:
#   /basicspacedata/query/class/gp/NORAD_CAT_ID/25544/predicates/OBJECT_NAME,EPOCH,INCLINATION,PERIOD/format/json

# 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()}")
# Distinct with metadata:
#   /basicspacedata/query/class/satcat/COUNTRY/US/metadata/true/distinct/true/format/json
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());
    // Ordered and limited:
    //   /basicspacedata/query/class/gp/NORAD_CAT_ID/25544/orderby/EPOCH desc/limit/5/format/json

    // 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());
    // Paginated results:
    //   /basicspacedata/query/class/gp/OBJECT_TYPE/PAYLOAD/orderby/NORAD_CAT_ID asc/limit/10,20/format/json

    // 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());
    // Filtered fields:
    //   /basicspacedata/query/class/gp/NORAD_CAT_ID/25544/predicates/OBJECT_NAME,EPOCH,INCLINATION,PERIOD/format/json

    // 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());
    // 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()}")
# Default (JSON):
#   /basicspacedata/query/class/gp/NORAD_CAT_ID/25544/format/json

# 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()}")
# TLE format:
#   /basicspacedata/query/class/gp/NORAD_CAT_ID/25544/format/tle

# 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()}")
# CSV format:
#   /basicspacedata/query/class/satcat/COUNTRY/US/limit/10/format/csv

# 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()}")
# KVN format:
#   /basicspacedata/query/class/gp/NORAD_CAT_ID/25544/format/kvn
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());
    // Default (JSON):
    //   /basicspacedata/query/class/gp/NORAD_CAT_ID/25544/format/json

    // 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());
    // TLE format:
    //   /basicspacedata/query/class/gp/NORAD_CAT_ID/25544/format/tle

    // 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());
    // CSV format:
    //   /basicspacedata/query/class/satcat/COUNTRY/US/limit/10/format/csv

    // 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());
    // 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