sdk/planetarycomputer/Azure.Analytics.PlanetaryComputer/README.md
The Azure Planetary Computer client library provides programmatic access to Microsoft Planetary Computer Pro, a geospatial data management service built on Azure's hyperscale infrastructure. Microsoft Planetary Computer Pro empowers organizations to unlock the full potential of geospatial data by providing foundational capabilities to ingest, manage, search, and distribute geospatial datasets using the SpatioTemporal Asset Catalog (STAC) open specification.
This client library enables developers to interact with GeoCatalog resources, supporting workflows from gigabytes to tens of petabytes of geospatial data.
Use the client library for Azure Planetary Computer to:
Source code | Product documentation
<!-- | [Package (NuGet)][pc_nuget] --> <!-- | [API reference documentation][pc_ref_docs] -->Install the client library for .NET with NuGet:
dotnet add package Azure.Analytics.PlanetaryComputer --prerelease
To interact with your GeoCatalog resource, create an instance of the client with your GeoCatalog endpoint and credentials.
Microsoft Entra ID authentication is required to ensure secure, unified enterprise identity and access management for your geospatial data.
To use the DefaultAzureCredential provider shown below, or other credential providers from the Azure SDK, install the Azure.Identity package:
dotnet add package Azure.Identity
You will also need to register a new Microsoft Entra ID application and grant access to your GeoCatalog by assigning the appropriate role to your service principal.
string endpoint = "https://your-endpoint.geocatalog.spatio.azure.com";
PlanetaryComputerProClient client = new PlanetaryComputerProClient(
new Uri(endpoint),
new DefaultAzureCredential());
// Get specific clients for different operations
StacClient stacClient = client.GetStacClient();
DataClient dataClient = client.GetDataClient();
IngestionClient ingestionClient = client.GetIngestionClient();
ManagedStorageSharedAccessSignatureClient sasClient = client.GetManagedStorageSharedAccessSignatureClient();
The StacClient provides operations for managing STAC collections and items:
The TilerClient provides operations for data visualization and tiling:
The IngestionClient provides operations for data ingestion management:
The SharedAccessSignatureClient provides operations for secure access:
We guarantee that all client instance methods are thread-safe and independent of each other (guideline). This ensures that the recommendation of reusing client instances is always safe, even across threads.
Client options | Accessing the response | Long-running operations | Handling failures | Diagnostics | Mocking | Client lifetime
<!-- CLIENT COMMON BAR -->The following section provides several code snippets covering common GeoCatalog workflows.
List all available STAC collections:
// Create a Planetary Computer client
Uri endpoint = new Uri("https://contoso-catalog.gwhqfdeddydpareu.uksouth.geocatalog.spatio.azure.com");
PlanetaryComputerProClient client = new PlanetaryComputerProClient(endpoint, new DefaultAzureCredential());
StacClient stacClient = client.GetStacClient();
// List all available STAC collections
Response<StacCatalogCollections> response = await stacClient.GetCollectionsAsync();
StacCatalogCollections collections = response.Value;
Console.WriteLine($"Found {collections.Collections.Count} collections:");
foreach (StacCollectionResource collection in collections.Collections)
{
Console.WriteLine($" - {collection.Id}: {collection.Title}");
}
Search for geospatial data items with spatial filters:
// Create a Planetary Computer client
Uri endpoint = new Uri("https://contoso-catalog.gwhqfdeddydpareu.uksouth.geocatalog.spatio.azure.com");
PlanetaryComputerProClient client = new PlanetaryComputerProClient(endpoint, new DefaultAzureCredential());
StacClient stacClient = client.GetStacClient();
// Search for items within a bounding box using CQL2-JSON
var searchParams = new StacSearchParameters();
searchParams.Collections.Add("naip");
searchParams.FilterLang = FilterLanguage.Cql2Json;
// Define a spatial filter for Atlanta, Georgia area
searchParams.Filter["op"] = BinaryData.FromString("\"s_intersects\"");
searchParams.Filter["args"] = BinaryData.FromObjectAsJson(new object[]
{
new Dictionary<string, string> { ["property"] = "geometry" },
new Dictionary<string, object>
{
["type"] = "Polygon",
["coordinates"] = new[]
{
new[]
{
new[] { -84.46, 33.60 },
new[] { -84.39, 33.60 },
new[] { -84.39, 33.67 },
new[] { -84.46, 33.67 },
new[] { -84.46, 33.60 }
}
}
}
});
searchParams.Limit = 10;
Response<StacItemCollectionResource> response = await stacClient.SearchAsync(searchParams);
StacItemCollectionResource results = response.Value;
Console.WriteLine($"Found {results.Features.Count} items in the specified area");
foreach (StacItemResource item in results.Features)
{
Console.WriteLine($" Item: {item.Id}");
}
Retrieve detailed information about a specific STAC item:
// Create a Planetary Computer client
Uri endpoint = new Uri("https://contoso-catalog.gwhqfdeddydpareu.uksouth.geocatalog.spatio.azure.com");
PlanetaryComputerProClient client = new PlanetaryComputerProClient(endpoint, new DefaultAzureCredential());
StacClient stacClient = client.GetStacClient();
// Get a specific item by ID
string collectionId = "naip";
string itemId = "tx_m_2609719_se_14_060_20201216";
Response<StacItemResource> response = await stacClient.GetItemAsync(collectionId, itemId);
StacItemResource item = response.Value;
Console.WriteLine($"Item ID: {item.Id}");
Console.WriteLine($"Collection: {item.Collection}");
Console.WriteLine($"Datetime: {item.Properties?.Datetime}");
Console.WriteLine($"\nAvailable Assets:");
foreach (var asset in item.Assets)
{
Console.WriteLine($" {asset.Key}: {asset.Value.Href}");
}
Create a new STAC collection for organizing geospatial data:
// Create a Planetary Computer client
Uri endpoint = new Uri("https://contoso-catalog.gwhqfdeddydpareu.uksouth.geocatalog.spatio.azure.com");
PlanetaryComputerProClient client = new PlanetaryComputerProClient(endpoint, new DefaultAzureCredential());
StacClient stacClient = client.GetStacClient();
// Define collection ID
string collectionId = "my-test-collection";
// Define spatial extent (global coverage)
var spatialExtent = new StacExtensionSpatialExtent();
spatialExtent.BoundingBox.Add(new List<float> { -180.0f, -90.0f, 180.0f, 90.0f });
// Define temporal extent
var temporalExtent = new StacCollectionTemporalExtent(
new[] { new List<string> { "2018-01-01T00:00:00Z", "2018-12-31T23:59:59Z" } }
);
// Combine spatial and temporal extents
var extent = new StacExtensionExtent(spatialExtent, temporalExtent);
// Create collection resource
var collection = new StacCollectionResource(
id: collectionId,
description: "Test collection for demonstration",
links: new List<StacLink>(),
license: "CC-BY-4.0",
extent: extent)
{
StacVersion = "1.0.0",
Title = "Test Collection",
Type = "Collection"
};
// Start collection creation (asynchronous operation)
Operation createOperation = await stacClient.CreateCollectionAsync(
WaitUntil.Started,
collection
);
Console.WriteLine($"Collection creation started: {collectionId}");
Console.WriteLine("Note: Collection creation is asynchronous and may take time to complete");
Generate map tiles from geospatial data:
// Create a Planetary Computer client
Uri endpoint = new Uri("https://contoso-catalog.gwhqfdeddydpareu.uksouth.geocatalog.spatio.azure.com");
PlanetaryComputerProClient client = new PlanetaryComputerProClient(endpoint, new DefaultAzureCredential());
DataClient dataClient = client.GetDataClient();
string collectionId = "naip";
string itemId = "tx_m_2609719_se_14_060_20201216";
// Get a specific tile
Response<BinaryData> response = await dataClient.GetTileAsync(
collectionId: collectionId,
itemId: itemId,
tileMatrixSetId: "WebMercatorQuad",
z: 14,
x: 4349,
y: 6564,
scale: 1,
format: "png",
assets: new[] { "image" },
assetBandIndices: "image|1,2,3"
);
byte[] tileImage = response.Value.ToArray();
Console.WriteLine($"Tile image: {tileImage.Length} bytes");
Manage data ingestion operations:
// Create a Planetary Computer client
Uri endpoint = new Uri("https://contoso-catalog.gwhqfdeddydpareu.uksouth.geocatalog.spatio.azure.com");
PlanetaryComputerProClient client = new PlanetaryComputerProClient(endpoint, new DefaultAzureCredential());
IngestionClient ingestionClient = client.GetIngestionClient();
string collectionId = "my-collection";
string sourceCatalogUrl = "https://example.com/catalog.json";
// Step 1: Create an ingestion definition
var ingestionDefinition = new IngestionInformation("StaticCatalog")
{
DisplayName = "My Dataset Ingestion",
SourceCatalogUrl = new Uri(sourceCatalogUrl),
KeepOriginalAssets = true,
SkipExistingItems = true
};
Response<IngestionInformation> createResponse = await ingestionClient.CreateAsync(
collectionId,
ingestionDefinition);
Guid ingestionId = createResponse.Value.Id;
Console.WriteLine($"Created ingestion: {ingestionId}");
// Step 2: Create and start an ingestion run
Response<IngestionRun> runResponse = await ingestionClient.CreateRunAsync(collectionId, ingestionId);
Guid runId = runResponse.Value.Id;
Console.WriteLine($"Started ingestion run: {runId}");
// Step 3: Monitor the run progress
Response<IngestionRun> statusResponse = await ingestionClient.GetRunAsync(collectionId, ingestionId, runId);
IngestionRun run = statusResponse.Value;
Console.WriteLine($"Run Status: {run.Operation.Status}");
Console.WriteLine($"Progress: {run.Operation.TotalSuccessfulItems}/{run.Operation.TotalItems} items");
// Step 4: List all runs for this ingestion
Console.WriteLine("\nAll runs for this ingestion:");
await foreach (IngestionRun r in ingestionClient.GetRunsAsync(collectionId, ingestionId))
{
Console.WriteLine($" Run {r.Id}: {r.Operation.Status}");
}
Generate Shared Access Signatures for secure data access:
// Create a Planetary Computer client
Uri endpoint = new Uri("https://contoso-catalog.gwhqfdeddydpareu.uksouth.geocatalog.spatio.azure.com");
PlanetaryComputerProClient client = new PlanetaryComputerProClient(endpoint, new DefaultAzureCredential());
ManagedStorageSharedAccessSignatureClient sasClient = client.GetManagedStorageSharedAccessSignatureClient();
// Get a SAS token with default duration (24 hours)
string collectionId = "naip";
Response<SharedAccessSignatureToken> response = await sasClient.GetTokenAsync(collectionId);
SharedAccessSignatureToken token = response.Value;
Console.WriteLine($"SAS Token: {token.Token.Substring(0, 50)}...");
Console.WriteLine($"Expires On: {token.ExpiresOn:yyyy-MM-dd HH:mm:ss} UTC");
When you interact with Azure Planetary Computer using the .NET SDK, errors returned by the service correspond to the same HTTP status codes returned for REST API requests.
For example, if you try to retrieve a collection that doesn't exist, a 404 error is returned, indicating Resource Not Found.
PlanetaryComputerProClient client = new PlanetaryComputerProClient(
new Uri(endpoint),
new DefaultAzureCredential());
StacClient stacClient = client.GetStacClient();
try
{
Response<StacCollectionResource> response = await stacClient.GetCollectionAsync(
"nonexistent-collection");
}
catch (RequestFailedException ex) when (ex.Status == 404)
{
Console.WriteLine($"Collection not found: {ex.Message}");
}
This library uses the standard .NET EventSource for logging. Logs can be enabled by adding the following to your application:
using Azure.Core.Diagnostics;
// Enable logging for Azure SDK
using AzureEventSourceListener listener = AzureEventSourceListener.CreateConsoleLogger();
For more detailed logging, including request/response bodies, use the DiagnosticsOptions:
PlanetaryComputerProClientOptions options = new PlanetaryComputerProClientOptions
{
Diagnostics =
{
IsLoggingEnabled = true,
IsLoggingContentEnabled = true,
LoggedContentSizeLimit = 4096
}
};
PlanetaryComputerProClient client = new PlanetaryComputerProClient(
new Uri(endpoint),
new DefaultAzureCredential(),
options);
This project welcomes contributions and suggestions. Most contributions require you to agree to a Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us the rights to use your contribution. For details, visit cla.microsoft.com.
When you submit a pull request, a CLA-bot will automatically determine whether you need to provide a CLA and decorate the PR appropriately (e.g., label, comment). Simply follow the instructions provided by the bot. You will only need to do this once across all repos using our CLA.
This project has adopted the Microsoft Open Source Code of Conduct. For more information see the Code of Conduct FAQ or contact [email protected] with any additional questions or comments.
<!-- LINKS --> <!-- [pc_nuget]: https://www.nuget.org/packages/Azure.Analytics.PlanetaryComputer --> <!-- [pc_ref_docs]: https://learn.microsoft.com/dotnet/api/azure.analytics.planetarycomputer --> <!-- [pc_samples]: https://github.com/Azure/azure-sdk-for-net/tree/main/sdk/planetarycomputer/Azure.Analytics.PlanetaryComputer/samples -->