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.1.tar.gz (23.1 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.1-py3-none-any.whl (20.3 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: scope3track-1.0.1.tar.gz
  • Upload date:
  • Size: 23.1 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.1.tar.gz
Algorithm Hash digest
SHA256 b2e582e17408d0dcb70079b463bf82ab13456d942745421b80587d4eac3d239e
MD5 73dbb85cfc6132d5c9d4f36e92e90809
BLAKE2b-256 c6f4db2c89e1c760e82f1ccd08d630cf0f7826146ce5162e3cf2e07136983bc8

See more details on using hashes here.

File details

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

File metadata

  • Download URL: scope3track-1.0.1-py3-none-any.whl
  • Upload date:
  • Size: 20.3 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.1-py3-none-any.whl
Algorithm Hash digest
SHA256 20d89f66649df2ec389ec7880992d629f4d1f90db386423ac30e1d71850c282b
MD5 33680313f6febd73cc5a92381cbd810f
BLAKE2b-256 61347baa63e1dcd37074e5fd0d52e2400d8474feb7930d8079dbda512d0b4fb6

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