Skip to main content

Carbon and Scope 3 emissions tracking for SMBs — GHG Protocol compliant calculations, supplier tracking, CSRD-ready reporting

Project description

scope3track

Carbon and Scope 3 emissions tracking for SMBs and enterprise supply chains — GHG Protocol-compliant calculations, supplier-level tracking, CSRD-ready reporting.

Enterprise carbon tools cost $30K–$150K/year. scope3track brings the same capability to Python developers for free.

PyPI version Python 3.8+

The Problem

EU CSRD enforcement + enterprise Scope 3 requirements are now cascading to SMB suppliers. Companies are required to report their full value-chain emissions. Enterprise tools cost $30K–$150K/year — nothing exists at the $99–$499/mo SMB price point.

Installation

pip install scope3track

Quick Start

from scope3track import EmissionCalculator, EmissionScope, Scope3Category
from datetime import datetime

calc = EmissionCalculator()

# Calculate Scope 3 Category 4: upstream transport
transport_entry = calc.calculate(
    entry_id="ENT-001",
    scope=EmissionScope.SCOPE3,
    category=Scope3Category.UPSTREAM_TRANSPORT,
    source="Freight — Shanghai to LA",
    activity_amount=5000,    # kg of freight
    activity_unit="kg",
    factor_key="km_road_freight_hgv",
    period_start=datetime(2025, 1, 1),
    period_end=datetime(2025, 3, 31),
    supplier_id="SUPPLIER-CN-01",
)

print(f"{transport_entry.emissions_kg_co2e:.2f} kg CO2e")

Build a Full Report

entries = [
    calc.calculate("e1", EmissionScope.SCOPE1, "Natural gas heating", 10000, "kwh", "kwh_natural_gas", period_start=..., period_end=...),
    calc.calculate("e2", EmissionScope.SCOPE2, "Office electricity", 50000, "kwh", "kwh_electricity_us", period_start=..., period_end=...),
    calc.calculate("e3", EmissionScope.SCOPE3, "Employee commuting", 200000, "km", "km_passenger_car", category=Scope3Category.EMPLOYEE_COMMUTING, period_start=..., period_end=...),
]

report = calc.build_report(
    company_id="ACME-INC",
    reporting_year=2025,
    entries=entries,
)

print(report.summary())
# {'company_id': 'ACME-INC', 'scope1_t_co2e': 2.02, 'scope2_t_co2e': 19.3, 'scope3_t_co2e': 34.2, 'total_t_co2e': 55.52, ...}

Built-in Emission Factors

scope3track ships with GHG Protocol default factors for:

  • Energy: electricity (US/EU grid), natural gas
  • Transport: road freight, air freight, sea freight, passenger car, business flights
  • Materials: steel, aluminium, plastic, paper, concrete
  • Waste: landfill, recycled, composted

Register custom factors:

from scope3track import default_registry

default_registry.register("kwh_solar_ppa", 0.012)

Scope 3 Categories Supported

All 15 GHG Protocol Scope 3 categories (upstream + downstream):

purchased_goods_services, capital_goods, fuel_and_energy_activities, upstream_transportation_distribution, waste_generated_in_operations, business_travel, employee_commuting, upstream_leased_assets, downstream_transportation_distribution, processing_of_sold_products, use_of_sold_products, end_of_life_treatment, downstream_leased_assets, franchises, investments

Advanced Features

Pipeline

from scope3track import EmissionPipeline

pipeline = (
    EmissionPipeline()
    .filter(lambda e: e.scope == EmissionScope.SCOPE3, name="scope3_only")
    .map(lambda entries: sorted(entries, key=lambda e: -e.emissions_kg_co2e), name="sort_by_impact")
    .with_retry(count=2)
)

scope3_sorted = pipeline.run(entries)

Caching

from scope3track import EmissionCache

cache = EmissionCache(max_size=1000, ttl_seconds=3600)

@cache.memoize
def get_supplier_emissions(supplier_id):
    ...

cache.save("emissions_cache.pkl")
cache.load("emissions_cache.pkl")
print(cache.stats())

Export Reports

from scope3track import EmissionReportExporter

print(EmissionReportExporter.to_json(report))
print(EmissionReportExporter.to_csv(report))
print(EmissionReportExporter.to_markdown(report))

Drift Detection

from scope3track import EmissionDriftDetector

detector = EmissionDriftDetector(threshold=0.15)
for period_total in quarterly_totals:
    detector.record(period_total)

if detector.is_drifted():
    print(f"Emission drift detected: {detector.drift_ratio():.1%}")

Diff Between Periods

from scope3track import diff_entries

diff = diff_entries(q1_entries, q2_entries)
print(diff.summary())  # {'added': 2, 'removed': 0, 'modified': 3}
print(diff.to_json())

Async Batch

from scope3track import abatch_calculate, CancellationToken

token = CancellationToken()
entries = await abatch_calculate(raw_data, calc_fn, max_concurrency=8, token=token)

Streaming NDJSON

from scope3track import entries_to_ndjson

for line in entries_to_ndjson(entries):
    output_stream.write(line)

Frameworks Supported

  • GHG Protocol Corporate Standard
  • EU CSRD / ESRS E1
  • ISO 14064-1

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

scope3track-1.0.0.tar.gz (15.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

scope3track-1.0.0-py3-none-any.whl (12.1 kB view details)

Uploaded Python 3

File details

Details for the file scope3track-1.0.0.tar.gz.

File metadata

  • Download URL: scope3track-1.0.0.tar.gz
  • Upload date:
  • Size: 15.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.9

File hashes

Hashes for scope3track-1.0.0.tar.gz
Algorithm Hash digest
SHA256 f10f2c52c3d59855d20b66e36161e9959452a29cae4d1544027c51aceaa45729
MD5 c71b39f2f859b2115dd8aedbde214f88
BLAKE2b-256 0ba314a72026117b45fa90d9a5555067e15263d0b9c836b0fadb8354f620124b

See more details on using hashes here.

File details

Details for the file scope3track-1.0.0-py3-none-any.whl.

File metadata

  • Download URL: scope3track-1.0.0-py3-none-any.whl
  • Upload date:
  • Size: 12.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.9

File hashes

Hashes for scope3track-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 0a3591a3d0e05badb036b1fead84f03500cadc2748fb475c76830d1d95e32cdb
MD5 406c301d989c878d941e3730b0621ba6
BLAKE2b-256 d08a87032850da9ce87e3b22ab6f06ce51f4b3e1523208237e5f6a91fbe52d87

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page