Skip to main content

Carbon and Scope 3 emissions tracking — GHG Protocol, emission hotspot analysis, Net Zero roadmap generation, SBTi alignment, 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.2.0.tar.gz (26.4 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.2.0-py3-none-any.whl (23.6 kB view details)

Uploaded Python 3

File details

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

File metadata

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

File hashes

Hashes for scope3track-1.2.0.tar.gz
Algorithm Hash digest
SHA256 6dc08837025d6fc60e9c71e081cc0738b06783569a713613c281b8c03ee9e828
MD5 9849f3848d56d4893a14c5f1c42751f8
BLAKE2b-256 af7d8f8b2ff512f516814a8693b7bbc4f53bb40988bbce17bc7e7c243b734e89

See more details on using hashes here.

File details

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

File metadata

  • Download URL: scope3track-1.2.0-py3-none-any.whl
  • Upload date:
  • Size: 23.6 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.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 b956d580056c5636eeb2a0106acd7f0501a5b3344d71b58241d41f2d8094d1ec
MD5 7606f0a964f21a2d833149720e7177ae
BLAKE2b-256 75757fe2ba20767c4d7d35e129e43dca8c8735e6b12367b6def920f8f9fe8239

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