Skip to main content

utilix-sdk

543 developer utility functions for Python: runs entirely locally, no API key required.

PyPI version Python 3.11+ License: MIT


Installation

pip install utilix-sdk

Requires Python 3.11 or later.


Quick Start

Encoding

from utilix.tools.encoding import encode_base64, decode_base64

result = encode_base64("hello world")
# {"ok": True, "output": "aGVsbG8gd29ybGQ=", "inputBytes": 11, "outputChars": 16}

result = decode_base64("aGVsbG8gd29ybGQ=")
# {"ok": True, "output": "hello world", "outputBytes": 11}

Hashing

from utilix.tools.hashing import hash_all, hash_one

result = hash_all("my-secret")
# Returns MD5, SHA-1, SHA-256, SHA-384, SHA-512 digests in one call

sha256 = hash_one("SHA-256", "my-secret")
# {"ok": True, "algorithm": "SHA-256", "hex": "...", "bits": 256}

from utilix.tools.hashing import generate_sri_all

# Subresource Integrity hashes for a script/stylesheet's content (SHA-256/384/512)
generate_sri_all("console.log(1)")
# {"ok": True, "output": [{"algorithm": "SHA-256", "base64": "...", "integrity": "sha256-..."}, ...]}

from utilix.tools.hashing import generate_etag

# Content-hash ETag header value (MD5/SHA-1/SHA-256), with an optional weak (W/) prefix
generate_etag("console.log(1)")
# {"ok": True, "output": {"algorithm": "SHA-1", "weak": False, "hash": "...", "etag": "\"...\"", "snippet": "ETag: \"...\""}}

JSON Tools

from utilix.tools.json_tools import format_json, minify_json, yaml_to_json, resolve_json_pointer, apply_json_merge_patch

pretty = format_json('{"name":"utilix","version":"0.1.0"}', indent=2)
# {"status": "valid", "output": "{\n  \"name\": \"utilix\", ...", ...}

minified = minify_json('{\n  "a": 1,\n  "b": 2\n}')
# {"ok": True, "output": "{\"a\":1,\"b\":2}", ...}

as_json = yaml_to_json("name: utilix\nversion: 0.1.0")
# {"ok": True, "output": "{\"name\": \"utilix\", \"version\": \"0.1.0\"}"}

pointer = resolve_json_pointer('{"users":[{"name":"Alice"}]}', "/users/0/name")
# {"ok": True, "found": True, "value": "Alice", "tokens": ["users", "0", "name"]}

patched = apply_json_merge_patch('{"a":"b","c":{"d":"e","f":"g"}}', '{"a":"z","c":{"f":null}}')
# {"ok": True, "output": {"result": {"a": "z", "c": {"d": "e"}}}}

Color

from utilix.tools.color import hex_to_rgb, check_contrast, generate_palette

rgb = hex_to_rgb("#3B82F6")
# {"ok": True, "r": 59, "g": 130, "b": 246}

contrast = check_contrast("#FFFFFF", "#3B82F6")
# {"ratio": 3.94, "aa_normal": False, "aa_large": True, "aaa_normal": False, ...}

palette = generate_palette("#3B82F6", scheme="complementary")
# Returns list of hex colors forming a complementary palette

Media

from utilix.tools.media import compress_image, convert_image, read_image_info, read_exif_data, read_pdf_metadata, read_pdf_page_dimensions, read_wav_info, read_id3_tags, read_ico_info, read_flac_info, read_video_info, inspect_gif_frames

with open("photo.jpg", "rb") as f:
    image_bytes = f.read()

result = compress_image(image_bytes, quality=75, format="JPEG")
# {"ok": True, "output": bytes, "original_size": 204800, "compressed_size": 61440, "ratio": 0.3}

converted = convert_image(image_bytes, target_format="WEBP")
# {"ok": True, "output": bytes, "format": "WEBP"}

# Read format, dimensions, bit depth, and alpha channel straight from file
# bytes: no decoding, no Pillow required. Supports PNG, JPEG, GIF, WebP, BMP.
info = read_image_info(image_bytes)
# {"ok": True, "format": "jpeg", "width": 1920, "height": 1080, "bitDepth": 8, "colorType": "rgb"}

# Read camera make/model, orientation, timestamps, exposure settings, and
# GPS coordinates directly from a JPEG's EXIF data. JPEG only.
exif = read_exif_data(image_bytes)
# {"ok": True, "make": "Canon", "model": "EOS R5", "exposureTime": "1/125", "fNumber": 2.8, ...}

# Read title, author, dates, page count, and encryption flag from a PDF's
# trailer/Info dictionary: no PDF rendering library required.
with open("report.pdf", "rb") as f:
    pdf_metadata = read_pdf_metadata(f.read())
# {"ok": True, "version": "1.7", "pageCount": 12, "title": "Q3 Report", "author": "Jane Doe", ...}

# List each page's MediaBox width/height (points and inches), rotation, and
# orientation by walking the Root -> Pages -> Kids tree, inheriting from
# ancestor nodes as the PDF spec requires. Also flags common paper sizes.
with open("report.pdf", "rb") as f:
    page_dimensions = read_pdf_page_dimensions(f.read())
# {"ok": True, "version": "1.7", "pageCount": 12, "pages": [{"pageNumber": 1, "widthPt": 612, "heightPt": 792, "rotation": 0, "orientation": "portrait", "paperSize": "Letter"}, ...]}

# Read sample rate, channels, bit depth, and duration from a WAV file's
# RIFF/fmt/data chunk headers: no audio library required.
with open("recording.wav", "rb") as f:
    wav_info = read_wav_info(f.read())
# {"ok": True, "audioFormat": 1, "audioFormatLabel": "PCM", "channels": 2, "sampleRate": 44100, "bitsPerSample": 16, "durationSeconds": 12.4, ...}

# Read title, artist, album, year, genre, comment, and track number from an
# MP3's ID3 tags. Prefers ID3v2.3/2.4 text frames, falls back to the classic
# 128-byte ID3v1/1.1 trailer.
with open("track.mp3", "rb") as f:
    id3_tags = read_id3_tags(f.read())
# {"ok": True, "version": "ID3v2.3.0", "title": "Track Name", "artist": "Artist Name", "genre": "Rock", ...}

# Read how many images a .ico file embeds and each one's dimensions, color
# depth, and size directly from its ICONDIR/ICONDIRENTRY header table.
with open("favicon.ico", "rb") as f:
    ico_info = read_ico_info(f.read())
# {"ok": True, "imageCount": 3, "images": [{"width": 16, "height": 16, "bitCount": 32, ...}, ...]}

# Read sample rate, channels, bit depth, total samples, and duration from a
# FLAC file's STREAMINFO block, plus Vorbis comment tags (artist, title,
# album, ...) from its VORBIS_COMMENT block if present.
with open("track.flac", "rb") as f:
    flac_info = read_flac_info(f.read())
# {"ok": True, "sampleRate": 44100, "channels": 2, "bitsPerSample": 16, "durationSeconds": 214.7, "artist": "Artist Name", ...}

# Read duration, resolution, and video/audio codec identifiers from an MP4
# (ISO BMFF moov box) or WebM (EBML/Matroska Segment) container header: no
# frame decoding, demuxing, or transcoding.
with open("clip.mp4", "rb") as f:
    video_info = read_video_info(f.read())
# {"ok": True, "format": "mp4", "durationSeconds": 12.5, "width": 1920, "height": 1080, "videoCodec": "avc1", "audioCodec": "mp4a", ...}

# Walk a GIF87a/89a file's block structure (image descriptors, graphic
# control extensions, the NETSCAPE2.0 application extension) to report frame
# count, total animation duration, and loop count, without decoding any
# LZW-compressed pixel data.
with open("animation.gif", "rb") as f:
    gif_info = inspect_gif_frames(f.read())
# {"ok": True, "version": "89a", "width": 480, "height": 270, "frameCount": 24, "animated": True, "loopCount": 0, "totalDurationMs": 2400, ...}

CSS

from utilix.tools.css import generate_gradient, calc_specificity, minify_css

gradient = generate_gradient({
    "type": "linear",
    "angle": 135,
    "stops": [{"color": "#667eea", "position": 0}, {"color": "#764ba2", "position": 100}]
})
# "linear-gradient(135deg, #667eea 0%, #764ba2 100%)"

specificity = calc_specificity("#nav .item:hover")
# {"score": (0, 1, 1, 1), "display": "0,1,1,1", "explanation": [...]}

minified = minify_css("body {\n  margin: 0;\n  padding: 0;\n}")
# {"ok": True, "output": "body{margin:0;padding:0}", "saved_bytes": 14}

Time Tools

from utilix.tools.time_tools import from_unix, diff_dates, get_next_runs

parsed = from_unix(1735689600)
# {"ok": True, "iso": "2025-01-01T00:00:00+00:00", "relative": "6 months ago", ...}

delta = diff_dates("2024-01-01", "2024-12-31")
# {"ok": True, "days": 365, "months": 12, "human": "12 months"}

schedule = get_next_runs("0 9 * * MON-FRI", count=5)
# Next 5 weekday 9am runs as ISO strings

from utilix.tools.time_tools import parse_iso8601_duration, format_iso8601_duration

parse_iso8601_duration("P3DT4H30M")  # {"ok": True, "output": {"totalSeconds": 275400.0, ...}}
format_iso8601_duration(90061)       # {"ok": True, "output": {"iso": "P1DT1H1M1S", ...}}

Network

from utilix.tools.network import ip_to_decimal, cidr_info, is_valid_ipv4

decimal = ip_to_decimal("192.168.1.1")
# {"ok": True, "output": 3232235777}

subnet = cidr_info("10.0.0.0/24")
# {"ok": True, "network": "10.0.0.0", "broadcast": "10.0.0.255",
#  "hosts": 254, "netmask": "255.255.255.0", ...}

print(is_valid_ipv4("256.0.0.1"))  # False

from utilix.tools.network import parse_har, validate_sitemap, split_sitemap, validate_robots_txt

# Parse a DevTools .har network export into entries + summary stats
with open("network.har") as f:
    result = parse_har(f.read())
# {"ok": True, "output": {"entries": [...], "summary": {"totalRequests": 12, ...}}}

# Validate a sitemap.xml (or sitemap index) against the sitemaps.org protocol
validate_sitemap('<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"><url><loc>https://example.com/</loc></url></urlset>')
# {"ok": True, "output": {"type": "urlset", "urlCount": 1, "entries": [...], "issues": [...], "valid": True}}

# Split a URL list exceeding the 50,000-URL sitemap cap into multiple sitemap.xml files + a sitemap index
split_sitemap("https://example.com/a\nhttps://example.com/b\nhttps://example.com/c", base_url="https://example.com", urls_per_file=2)
# {"ok": True, "output": {"files": [{"filename": "sitemap-1.xml", "urlCount": 2, "xml": "..."}, ...], "indexXml": "...", "totalUrls": 3}}

# Validate a robots.txt file: User-agent groups, rules, and syntax mistakes
validate_robots_txt("User-agent: *\nDisallow: /admin\nSitemap: https://example.com/sitemap.xml")
# {"ok": True, "output": {"groups": [...], "sitemaps": [...], "issues": [...], "valid": True}}

from utilix.tools.network import parse_user_agent

# Parse a browser User-Agent string into browser, engine, OS, and device type
parse_user_agent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36")
# {"ok": True, "output": {"browser": {"name": "Chrome", "version": "120.0.0.0"},
#  "engine": {"name": "Blink", "version": "120.0.0.0"}, "os": {"name": "Windows", "version": "10"},
#  "device": {"type": "desktop"}, "raw": "..."}}

from utilix.tools.network import build_cache_control

# Build and explain a Cache-Control response header from directives
build_cache_control({"visibility": "public", "maxAge": 3600, "mustRevalidate": True})
# {"ok": True, "output": {"header": "public, max-age=3600, must-revalidate", "directives": [...], "warnings": []}}

from utilix.tools.network import parse_ipv6_address

# Expand/compress an IPv6 address (RFC 5952) and classify its address type
parse_ipv6_address("2001:db8::ff00:42:8329")
# {"ok": True, "output": {"expanded": "2001:0db8:0000:0000:0000:ff00:0042:8329",
#  "compressed": "2001:db8::ff00:42:8329", "groups": [...], "zoneId": None, "addressType": "documentation"}}

from utilix.tools.network import build_referrer_policy

# Build and explain a Referrer-Policy header from one or more fallback-chain tokens
build_referrer_policy("strict-origin-when-cross-origin")
# {"ok": True, "output": {"header": "strict-origin-when-cross-origin", "metaTag": "<meta name=\"referrer\" content=\"...\">", "policies": [...], "warnings": []}}

from utilix.tools.network import build_link_header

# Build an HTTP Link header from URL/rel pairs (preload, preconnect, canonical, pagination, etc.)
build_link_header([{"url": "/fonts/inter.woff2", "rel": "preload", "as": "font", "type": "font/woff2", "crossorigin": True}])
# {"ok": True, "output": {"header": '</fonts/inter.woff2>; rel="preload"; as="font"; type="font/woff2"; crossorigin', "links": [...], "warnings": []}}

from utilix.tools.network import check_set_cookie_header

# Parse and validate a Set-Cookie header's attribute combination
check_set_cookie_header("session=abc123; SameSite=None")
# {"ok": True, "output": {"cookie": {...}, "issues": ["SameSite=None requires the Secure attribute..."], "warnings": [...], "valid": False}}

from utilix.tools.network import analyze_email_headers

# Parse a raw email header block: fields, Received hop chain, SPF/DKIM/DMARC results
analyze_email_headers(raw_header_text)
# {"ok": True, "output": {"from": "...", "receivedHops": [...], "hopCount": 2, "spf": "pass", "dkim": "pass", "dmarc": "pass", "warnings": []}}

from utilix.tools.network import build_robots_meta_tag

# Build a <meta name="robots" content="..."> tag, the same directive vocabulary as X-Robots-Tag
build_robots_meta_tag(flags=["noindex", "nofollow"], name="googlebot")
# {"ok": True, "output": {"content": "noindex, nofollow", "name": "googlebot", "tag": '<meta name="googlebot" content="noindex, nofollow">', "directives": [...], "notes": [...], "warnings": []}}

from utilix.tools.code import analyze_regex_groups

# Parse a regex's capture groups and backreferences, flagging one that doesn't exist yet
analyze_regex_groups(r"(a)(b)\3")
# {"ok": True, "output": {"groups": [{"index": 1, ...}, {"index": 2, ...}], "backreferences": [{"raw": "\\3", "target": 3, "resolved": False, ...}], "issues": [{"severity": "error", "message": "Backreference \\3 ... doesn't exist ..."}]}}

from utilix.tools.code import extract_svg_sprite_symbols

# List an SVG sprite sheet's <symbol> definitions with id, viewBox, and a ready-to-paste <use> snippet
extract_svg_sprite_symbols('<svg><symbol id="icon-home" viewBox="0 0 24 24"></symbol></svg>')
# {"ok": True, "output": {"symbolCount": 1, "symbols": [{"id": "icon-home", "viewBox": "0 0 24 24", "width": None, "height": None, "usageSnippet": '<svg><use href="#icon-home"></use></svg>'}], "skippedCount": 0}}

from utilix.tools.code import parse_commit_trailers

# Parse a commit message's trailer block (Co-authored-by, Signed-off-by, Fixes, etc.) into key/value pairs plus the remaining body
parse_commit_trailers("Fix bug\n\nSigned-off-by: A <a@example.com>")
# {"ok": True, "output": {"trailers": [{"key": "Signed-off-by", "value": "A <a@example.com>"}], "body": "Fix bug", "hasTrailers": True}}

from utilix.tools.code import extract_markdown_footnotes

# Extract Markdown footnote references and definitions, flagging unresolved references and unused definitions
extract_markdown_footnotes("A claim[^1].\n\n[^1]: The source.")
# {"ok": True, "output": {"definitionCount": 1, "referenceCount": 1, "definitions": [{"label": "1", "text": "The source."}], "unresolvedReferences": [], "unusedDefinitions": []}}

from utilix.tools.code import test_gitignore_patterns

# Test paths against a .gitignore file's patterns
test_gitignore_patterns("node_modules/\n*.log", ["node_modules/foo.js", "debug.log", "src/index.js"])
# {"ok": True, "output": [{"path": "node_modules/foo.js", "ignored": True, "matchedPattern": "node_modules/", "matchedLine": 1}, ...]}

from utilix.tools.code import validate_editorconfig

# Validate an .editorconfig file's syntax and known property values
validate_editorconfig("root = true\n\n[*]\nindent_style = space\nindent_size = 2\n")
# {"ok": True, "output": {"root": True, "sections": [{"glob": "*", "properties": [...]}], "issues": [], "valid": True}}

from utilix.tools.code import validate_tsconfig

# Validate a tsconfig.json file (JSONC comments and trailing commas are stripped first)
validate_tsconfig('{"compilerOptions": {"target": "ES2020", "strict": true}}')
# {"ok": True, "output": {"parsed": True, "topLevelKeys": ["compilerOptions"], "compilerOptionKeys": ["target", "strict"], "issues": [], "valid": True}}

from utilix.tools.code import validate_package_exports

# Validate a package.json "exports" field for dual-package (ESM/CJS) misconfigurations
validate_package_exports('{"exports": {"import": "./index.mjs", "require": "./index.cjs", "default": "./index.cjs"}}')
# {"ok": True, "output": {"parsed": True, "exportsShape": "conditions", "subpaths": ["."], "issues": [], "valid": True}}

from utilix.tools.network import build_x_content_type_options_header, assess_content_type_risk

# Build the fixed X-Content-Type-Options header, with a plain-English explanation of the MIME-sniffing attack it prevents
build_x_content_type_options_header()
# {"ok": True, "output": {"header": "X-Content-Type-Options: nosniff", "value": "nosniff", "explanation": "..."}}

# Assess how risky it is to serve a given Content-Type without X-Content-Type-Options: nosniff
assess_content_type_risk("text/plain")
# {"ok": True, "output": {"contentType": "text/plain", "risk": "high", "reason": "..."}}

from utilix.tools.data import generate_markdown_toc

# Markdown table of contents: ATX headings -> nested links with GitHub-style slugs
generate_markdown_toc("# Title\n\n## Section One\n\n## Section Two\n")
# {"ok": True, "output": {"toc": "- [Title](#title)\n  - [Section One](#section-one)\n  - [Section Two](#section-two)", "entries": [...]}}

from utilix.tools.units import compare_unit_prices

# True cost per unit across package options, flags the cheapest
compare_unit_prices([{"label": "12-pack", "price": 6, "quantity": 12}, {"label": "24-pack", "price": 10, "quantity": 24}])
# {"ok": True, "output": {"items": [...], "bestLabel": "24-pack"}}

from utilix.tools.data import csv_to_sql_insert

# CSV to SQL INSERT statements, with basic type inference and identifier quoting
csv_to_sql_insert("name,age\nAlice,30\nBob,25", {"tableName": "users"})
# {"ok": True, "output": {"sql": "INSERT INTO \"users\" (\"name\", \"age\") VALUES ('Alice', 30);\n...", "rowCount": 2, ...}}

from utilix.tools.network import build_range_header, parse_content_range_header

# Build a Range request header from explicit, open-ended, or suffix ("last N bytes") byte ranges
build_range_header([{"start": 0, "end": 1023}], {"totalSize": 146515})
# {"ok": True, "output": {"header": "Range: bytes=0-1023", "ranges": [...], "totalBytesRequested": 1024, "warnings": []}}

# Parse a Content-Range response header to verify what a server actually sent back
parse_content_range_header("bytes 200-1000/67589")
# {"ok": True, "output": {"unit": "bytes", "start": 200, "end": 1000, "total": 67589, "byteLength": 801, "isUnsatisfiable": False}}

from utilix.tools.network import build_vary_header, parse_vary_header

# Build a Vary response header from request-header names, with a plain-English caching note per header
build_vary_header(["Accept-Encoding", "Accept-Language"])
# {"ok": True, "output": {"header": "Vary: Accept-Encoding, Accept-Language", "entries": [...], "warnings": []}}

# Parse an existing Vary header value into the same shape
parse_vary_header("Vary: Accept-Encoding, Accept-Language")
# {"ok": True, "output": {"header": "Vary: Accept-Encoding, Accept-Language", "entries": [...], "warnings": []}}

from utilix.tools.network import validate_manifest

# Validate a web app manifest.json against the W3C spec's installability requirements
validate_manifest('{"name": "My App", "start_url": "/", "display": "standalone", "icons": [{"src": "/icon-512.png", "sizes": "512x512", "purpose": "any maskable"}]}')
# {"ok": True, "output": {"issues": [...], "valid": True, "summary": {"hasMaskableIcon": True, "has512Icon": True, ...}}}

from utilix.tools.data import find_csv_duplicate_rows

# Find duplicate rows in CSV/TSV data, by the whole row or a chosen key column set
find_csv_duplicate_rows("name,email\nAlice,a@x.com\nBob,b@x.com\nAlice,a@x.com")
# {"ok": True, "output": {"duplicateGroups": [{"key": ["Alice", "a@x.com"], "rowNumbers": [1, 3], "count": 2}], "duplicateRowCount": 2, ...}}

from utilix.tools.data import infer_csv_column_types

# Infer each CSV column's data type: integer, float, boolean, ISO 8601 date, or string
infer_csv_column_types("id,price,active\n1,9.99,true\n2,5,false")
# {"ok": True, "output": {"columns": [{"name": "id", "inferredType": "integer", ...}, {"name": "price", "inferredType": "float", ...}, ...], "rowCount": 2}}

from utilix.tools.network import build_permissions_policy, parse_permissions_policy

# Build a Permissions-Policy header from features and their allowlists, with a plain-English note per feature
build_permissions_policy([{"feature": "camera", "allowlist": []}, {"feature": "geolocation", "allowlist": ["self"]}])
# {"ok": True, "output": {"header": "Permissions-Policy: camera=(), geolocation=(self)", "directives": [...], "warnings": []}}

# Parse an existing Permissions-Policy header value into the same shape
parse_permissions_policy("camera=(), geolocation=(self)")
# {"ok": True, "output": {"header": "Permissions-Policy: camera=(), geolocation=(self)", "directives": [...], "warnings": []}}

from utilix.tools.units import calculate_payback_period, calculate_cd_maturity

# Payback period: simple + discounted, from an initial investment and periodic cash flows
calculate_payback_period(1000, [400, 400, 400], discount_rate_percent=8)
# {"ok": True, "output": {"paybackPeriod": 2.5, "paybackPeriodRounded": 3, "recovered": True, "discountedPaybackPeriod": 2.9029, ...}}

# Certificate of deposit maturity value, APY, and net early-withdrawal payout
calculate_cd_maturity(1000, 12, 12, 12, early_withdrawal_penalty_months=3)
# {"ok": True, "output": {"maturityValue": 1126.83, "totalInterest": 126.83, "apy": 12.6825, "earlyWithdrawalPayout": 1096.83, ...}}

from utilix.tools.network import build_client_hints, parse_client_hint_headers

# Build an Accept-CH header from a list of client hint names, with a plain-English note per hint
build_client_hints(["Sec-CH-UA-Platform", "Sec-CH-DPR"])
# {"ok": True, "output": {"acceptCH": "Sec-CH-UA-Platform, Sec-CH-DPR", "hints": [...]}}

# Decode raw Client Hints request-header text into structured values
parse_client_hint_headers("Sec-CH-UA-Mobile: ?0")
# {"ok": True, "output": {"hints": [{"name": "Sec-CH-UA-Mobile", "value": False, ...}], "unrecognized": []}}

from utilix.tools.units import calculate_depreciation_schedule

# Year-by-year depreciation schedule: straight-line, double-declining-balance, or sum-of-years-digits
calculate_depreciation_schedule(10000, 1000, 5, "straight-line")
# {"ok": True, "output": {"totalDepreciation": 9000.0, "schedule": [{"year": 1, "depreciationExpense": 1800.0, "accumulatedDepreciation": 1800.0, "bookValue": 8200.0}, ...]}}

from utilix.tools.units import calculate_cash_rounding

# Round a cashless total to the nearest payable cash denomination ("Swedish rounding")
calculate_cash_rounding(2.02, 0.05)
# {"ok": True, "output": {"total": 2.02, "roundingUnit": 0.05, "mode": "nearest", "roundedTotal": 2.0, "adjustment": -0.02}}

from utilix.tools.units import calculate_moving_averages

# Simple and exponential moving averages over a numeric series
calculate_moving_averages([102, 104, 101, 108, 112], 3)
# {"ok": True, "output": {"windowSize": 3, "multiplier": 0.5, "latestSma": 107.0, "latestEma": 108.5833, "points": [...]}}

from utilix.tools.units import calculate_gpa

# Weighted GPA from a list of courses (letter grade + credit hours)
calculate_gpa([{"name": "Calculus", "grade": "A", "credits": 4}, {"name": "History", "grade": "B+", "credits": 3}])
# {"ok": True, "output": {"gpa": 3.7, "totalCredits": 7.0, "totalQualityPoints": 25.9, "courses": [...]}}

from utilix.tools.units import calculate_credit_utilization

# Per-account and overall credit utilization, plus a qualitative tier
calculate_credit_utilization([{"label": "Visa", "balance": 500, "limit": 5000}, {"label": "Amex", "balance": 1200, "limit": 3000}])
# {"ok": True, "output": {"overallUtilizationPercent": 21.25, "overallTier": "good", "totalBalance": 1700.0, "totalLimit": 8000.0, "accounts": [...]}}

from utilix.tools.units import calculate_debt_to_income_ratio

# Debt-to-income (DTI) ratio, plus a qualitative tier matching common mortgage-lending guidance
calculate_debt_to_income_ratio([{"label": "Rent", "amount": 1500}, {"label": "Car loan", "amount": 400}], 5000)
# {"ok": True, "output": {"dtiPercent": 38.0, "tier": "moderate", "totalMonthlyDebt": 1900.0, "grossMonthlyIncome": 5000, "debts": [...]}}

from utilix.tools.data import calculate_markdown_task_list_progress

# Markdown task list progress: completion percentage overall and per heading section
calculate_markdown_task_list_progress("# Phase 1\n- [x] a\n- [x] b\n## Phase 2\n- [ ] c\n")
# {"ok": True, "output": {"totalItems": 3, "completedItems": 2, "percentComplete": 66.67, "sections": [{"section": "Phase 1", ...}, {"section": "Phase 2", ...}]}}

from utilix.tools.data import analyze_caption_speed

# Caption reading speed: flag SRT/WebVTT cues faster than ~180 WPM / ~20 chars/sec (both adjustable)
analyze_caption_speed("1\n00:00:01,000 --> 00:00:02,000\nThis line is read far too fast for anyone to follow.\n")
# {"ok": True, "output": {"cueCount": 1, "averageWpm": 660.0, "flaggedCount": 1, "cues": [{"wpm": 660.0, "exceedsWpm": True, ...}], ...}}

from utilix.tools.text import analyze_keyword_density

# Keyword/phrase frequency and density (occurrences per 100 words); ngram_size 2 or 3 for phrases
analyze_keyword_density("machine learning models power machine learning systems")
# {"ok": True, "output": {"totalWords": 7, "uniqueKeywords": 5, "ngramSize": 1, "keywords": [{"keyword": "learning", "count": 2, "density": 28.6}, ...]}}

from utilix.tools.network import build_content_disposition, parse_content_disposition

# Build a Content-Disposition header; non-ASCII filenames get an RFC 5987
# filename* parameter alongside an ASCII-sanitized fallback
build_content_disposition({"type": "attachment", "filename": "résumé.pdf"})
# {"ok": True, "output": {"header": "attachment; filename=\"r_sum_.pdf\"; filename*=UTF-8''r%C3%A9sum%C3%A9.pdf", "type": "attachment", "filename": "résumé.pdf", "filenameEncoded": True}}

# Parse an existing Content-Disposition header, decoding filename* in preference to filename
parse_content_disposition('attachment; filename="report.pdf"')
# {"ok": True, "output": {"type": "attachment", "filename": "report.pdf", "filenameIsExtended": False, "params": {"filename": "report.pdf"}}}

from utilix.tools.network import build_accept_language, parse_accept_language

# Build an Accept-Language header from locale/quality pairs, sorted by descending preference
build_accept_language([{"locale": "en-US"}, {"locale": "fr", "quality": 0.7}])
# {"ok": True, "output": {"header": "Accept-Language: en-US, fr;q=0.7", "headerValue": "en-US, fr;q=0.7", "entries": [...]}}

# Parse an existing Accept-Language header into its ranked locale/quality pairs
parse_accept_language("en-US,en;q=0.9,fr;q=0.8")
# {"ok": True, "output": {"entries": [{"locale": "en-US", "quality": 1.0}, {"locale": "en", "quality": 0.9}, {"locale": "fr", "quality": 0.8}]}}

from utilix.tools.network import build_prefer_header, parse_prefer_header

# Build a Prefer request-header value from preferences with optional values/params, per RFC 7240
build_prefer_header([{"token": "respond-async"}, {"token": "wait", "value": "100"}])
# {"ok": True, "output": {"header": "Prefer: respond-async, wait=100", "headerValue": "respond-async, wait=100", "preferences": [...]}}

# Parse an existing Prefer header value into the same shape
parse_prefer_header("return=minimal;handling=lenient")
# {"ok": True, "output": {"headerValue": "return=minimal;handling=lenient", "preferences": [...]}}

from utilix.tools.data import dedupe_ndjson

# Remove duplicate NDJSON records, by exact match or by a key field
dedupe_ndjson('{"id":1}\n{"id":2}\n{"id":1}')
# {"ok": True, "output": {"totalLines": 3, "uniqueLines": 2, "duplicatesRemoved": 1, "output": "{\"id\":1}\n{\"id\":2}", "removedLines": [3]}}

from utilix.tools.network import build_retry_after_header, parse_retry_after_header

# Build a Retry-After response header from a delay in seconds or a target date, per RFC 9110
build_retry_after_header(seconds=120)
# {"ok": True, "output": {"header": "Retry-After: 120", "headerValue": "120", "type": "seconds", "seconds": 120}}

# Parse an existing Retry-After header value into the same shape
parse_retry_after_header("Retry-After: 120")
# {"ok": True, "output": {"header": "Retry-After: 120", "headerValue": "120", "type": "seconds", "seconds": 120}}

from utilix.tools.network import build_priority_header, parse_priority_header, lookup_close_code, list_close_codes

# Build a Priority request/response header from urgency (0-7) and/or incremental, per RFC 9218
build_priority_header(urgency=1, incremental=True)
# {"ok": True, "output": {"header": "Priority: u=1, i", "headerValue": "u=1, i", "urgency": 1, "incremental": True}}

# Parse an existing Priority header value into the same shape, with spec defaults applied
parse_priority_header("u=2")
# {"ok": True, "output": {"header": "Priority: u=2, i=?0", "headerValue": "u=2, i=?0", "urgency": 2, "incremental": False}}

# Look up what a WebSocket close code means, per RFC 6455 and the IANA reserved ranges
lookup_close_code(1006)
# {"ok": True, "output": {"code": 1006, "name": "Abnormal Closure", "range": "standard", "sentOnWire": False, ...}}

# List every well-known WebSocket close code (1000-1015)
list_close_codes()
# {"ok": True, "output": {"codes": [{"code": 1000, "name": "Normal Closure", ...}, ...]}}

from utilix.tools.network import parse_multipart_form_data, extract_multipart_boundary

# Parse a raw multipart/form-data request body into its individual parts, per RFC 7578
parse_multipart_form_data('--X\r\nContent-Disposition: form-data; name="a"\r\n\r\nhello\r\n--X--\r\n', "X")
# {"ok": True, "output": {"boundary": "X", "parts": [{"name": "a", "filename": None, "headers": {...}, "value": "hello", "isBinary": False}]}}

# Extract the boundary parameter from a Content-Type header value
extract_multipart_boundary("multipart/form-data; boundary=----WebKitFormBoundaryABC123")
# "----WebKitFormBoundaryABC123"

from utilix.tools.units import calculate_blended_loan_rate, calculate_freelancer_rate, calculate_extra_payment_payoff, calculate_loan_refinance

# Weighted-average blended interest rate across a list of loan balances, plus combined monthly/annual interest
calculate_blended_loan_rate([{"label": "Card A", "balance": 10000, "ratePercent": 20}, {"label": "Card B", "balance": 5000, "ratePercent": 5}])
# {"ok": True, "output": {"weightedAverageRatePercent": 15.0, "totalBalance": 15000.0, "totalMonthlyInterest": 187.5, "totalAnnualInterest": 2250.0, "loans": [...]}}

# Minimum hourly rate to hit a target annual income, given billable hours, weeks worked, overhead, and margin
calculate_freelancer_rate(target_annual_income=80000, billable_hours_per_week=25, weeks_per_year=48)
# {"ok": True, "output": {"hourlyRate": 66.67, "dailyRate": 533.33, "requiredAnnualRevenue": 80000.0, "annualBillableHours": 1200.0, "monthlyRevenueTarget": 6666.67}}

# How much sooner a loan pays off, and how much interest is saved, with a fixed extra monthly payment
calculate_extra_payment_payoff(200000, 6, 360, 200)
# {"ok": True, "output": {"monthlyPayment": 1199.1, "newPayoffMonths": 252, "monthsSaved": 108, "interestSaved": 79800.88, ...}}

# Loan refinance break-even: monthly savings and the month closing costs are recouped
calculate_loan_refinance(300000, 6.5, 300, 5.5, 300, 6000)
# {"ok": True, "output": {"monthlySavings": 183.36, "breakEvenMonths": 33, "currentTotalInterest": 307687.31, "newTotalInterest": 252679.7, ...}}

Modules

Module Description
encoding Base64, Base32, Base58, Base62, URL encoding/decoding, HTML entity encoding
hashing MD5, SHA-1/256/384/512 digests, bcrypt password hashing, htpasswd, SRI hashes, content-hash ETag generation
json_tools JSON formatting, minification, diffing, CSV conversion, JSONPath, JSON Pointer (RFC 6901), JSON Merge Patch (RFC 7396), JSON Schema, YAML-JSON
color Color conversion (hex/RGB/HSL/HSV), palettes, contrast ratios, shades/tints, blending
css Gradients, box shadows, border radius, animations, cubic bezier, clamp, specificity, minifier
media Image compression, format conversion, favicon generation, SVG optimization, header-based format/dimension reading, PDF metadata reading, ICO favicon inspection, FLAC metadata reading, MP4/WebM video info, GIF frame/loop inspection
time_tools Unix timestamp parsing, cron expression parsing, date diffing, timezone conversion, ISO 8601 duration parsing/formatting
network IPv4 conversion, CIDR calculator, DNS lookup (DoH), IP geolocation, HAR file parsing, sitemap.xml validation, sitemap index splitting, robots.txt validation, User-Agent parsing, Cache-Control header builder, Permissions-Policy header builder, Client Hints header builder/parser, Content-Disposition header builder/parser, Prefer header builder/parser (RFC 7240), multipart/form-data body parser (RFC 7578), Strict-Transport-Security (HSTS) header builder/parser, X-Robots-Tag header builder/parser, WebSocket frame opcode reference/lookup, robots meta tag builder/parser
api_tools cURL builder/parser, cURL-to-code, JWT decode/sign, JWKS parsing, JWK thumbprint (RFC 7638), HTTP status codes, CORS/CSP builders, TOTP/HOTP code generator
code Regex tester, regex ReDoS detector, regex backreference & named group visualizer, SQL formatter, HTML formatter/minifier, GraphQL formatter, semver, URL parser, JS minifier, MIME type lookup, GitHub URL parser, Conventional Commits linter, package.json exports field validator, package.json dependency range auditor, SVG sprite symbol extractor
data YAML, TOML, XML, CSV, INI, NDJSON, and .env file parsing, validation, and conversion, NDJSON record deduplicator, SRT/WebVTT subtitle conversion, Markdown front matter parsing, YAML anchor/alias resolver, CSV column type inferencer, Markdown table column aligner
generators UUID v4/v7, ULID, password generator, password strength check, password entropy estimator, random data, QR code generation, CSP nonce generator
text Word counter, case converter, lorem ipsum, slugifier, string escaping, diff viewer, Markdown/HTML, passive voice detection, readability scoring, filler word & cliché detection, Levenshtein/Damerau string distance, sentence length distribution, keyword density analyzer, emoji lookup
misc Unicode analysis, ASCII art, Morse code, JSON-to-TypeScript/Go/Python/Zod schema generation, JSON Schema-to-TypeScript
units px/rem/vw conversions, byte formatter, number base conversion, aspect ratio, chmod calculator, credit card Luhn/network validator, IBAN validator, loan/mortgage calculator, EMI calculator, barcode checksum validator, ISBN validator, VAT/sales tax calculator, compound/simple interest calculators, present/future value calculator, percentage change calculator, APR/APY converter, margin & markup calculator, discount/markdown calculator, tip/bill split calculator, break-even point calculator, video bitrate & file size calculator, Rule of 72 calculator, savings goal calculator, ROI calculator, cash denomination/till calculator, payback period calculator, CD maturity calculator, depreciation schedule calculator, debt-to-income ratio calculator, debt snowball/avalanche payoff planner, loan refinance break-even calculator, tax-equivalent yield calculator
ai_agent Token estimate/trim, chunk text, extract URLs/JSON/keywords, sanitize HTML, flatten/merge JSON, dedupe lines, validate schema, PII/secret/injection detect, vector similarity, few-shot prompt formatter, tool-definition schema linter

Surface A vs Surface B

Surface A: this package (utilix-sdk)

Everything in this package runs locally in your Python process. There are no network calls for the core utilities (DNS lookup and IP geolocation are the only exceptions, and both hit public free APIs). No account, no API key, no rate limits.

pip install utilix-sdk

Ideal for: scripts, CI pipelines, offline environments, CLIs, and any situation where you want deterministic, zero-cost utility functions.

REST API (api.utilix.tech/v1)

The same 140+ tools are also available as a hosted REST API at https://api.utilix.tech/v1. This surface requires an API key and is subject to rate limits and pricing tiers.

curl -X POST https://api.utilix.tech/v1/tools/hash \
  -H "Authorization: Bearer $UTILIX_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"input": "hello world", "algorithm": "sha256"}'
  • Free: 1,000 requests/day: no credit card required
  • Pro: 10,000 requests/day: $9/month
  • Try it live at utilix.tech/api: no signup needed for the first 10 endpoints
  • Get your API key at utilix.tech/dashboard

Ideal for: polyglot teams, environments where installing Python packages is not possible, and browser-based tooling that needs a backend.


Contributing

The source for this package is maintained in a private monorepo; this repository holds examples, quickstarts, and the issue tracker. Found a bug or want to request a tool? Open an issue at github.com/utilix-tech/utilix-sdk/issues or email hello@utilix.tech.


Publishing to PyPI

Build the distribution

python -m build
# Produces dist/utilix_sdk-x.y.z.tar.gz and dist/utilix_sdk-x.y.z-py3-none-any.whl

Test on TestPyPI first

python -m twine upload --repository testpypi dist/*
# Install from TestPyPI to verify
pip install --index-url https://test.pypi.org/simple/ utilix-sdk

Publish to PyPI

python -m twine upload dist/*

Store no tokens. Configure a trusted publisher on PyPI (Settings > Publishing > Add a new publisher) and use the official PyPA action:

# .github/workflows/publish.yml
name: Publish to PyPI

on:
  push:
    tags:
      - "v*"

jobs:
  publish:
    runs-on: ubuntu-latest
    permissions:
      id-token: write  # Required for OIDC

    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-python@v5
        with:
          python-version: "3.11"

      - name: Build
        run: |
          pip install build
          python -m build

      - name: Publish to PyPI
        uses: pypa/gh-action-pypi-publish@release/v1
        # No api-token needed: OIDC trusted publisher handles auth

Tag a release (git tag v0.2.0 && git push --tags) and the workflow publishes automatically with no stored credentials.


License

MIT. See LICENSE for the full text.

Release files for utilix-sdk 0.70.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for utilix-sdk 0.70.0
File Size Uploaded
utilix_sdk-0.70.0.tar.gz 418.8 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for utilix-sdk 0.70.0
File Interpreter ABI Platform
utilix_sdk-0.70.0-py3-none-any.whl Python 3 none any Details

Total release size: 696.8 kB

Release files / utilix_sdk-0.70.0.tar.gz

Download URL utilix_sdk-0.70.0.tar.gz
Size 418.8 kB
Tags Source
SHA-256 checksum
How to use checksums
9d1a8f716054cebff3e5e25fcace93ae8820236a3ed758139e6832ccfe83d7bf
BLAKE2b-256 checksum
How to use checksums
0dfb9db8b0083a1640d2d591f64c36e81df9618da659f36f17371a3a6ed2ca6a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 25, 2026.

Transparency log

Release files / utilix_sdk-0.70.0-py3-none-any.whl

Download URL utilix_sdk-0.70.0-py3-none-any.whl
Size 278.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
341bf47dd5d4308a1be534ca1ea8b7957593f858b2d4d6388471a08e5205efd0
BLAKE2b-256 checksum
How to use checksums
c21fba23741833109b230d29a504ffe7a5d008d13d6b58e4c3672e7de6a4142a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 25, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.70.0 This release

2 release files

0.69.0

2 release files

0.68.0

2 release files

0.67.0

2 release files

0.66.0

2 release files

0.65.0

2 release files

0.64.0

2 release files

0.63.0

2 release files

0.62.0

2 release files

0.61.0

2 release files

0.60.0

2 release files

0.59.0

2 release files

0.57.0

2 release files

0.56.0

2 release files

0.50.0

2 release files

0.49.0

2 release files

0.48.0

2 release files

0.47.0

2 release files

0.46.0

2 release files

0.45.0

2 release files

0.44.0

2 release files

0.43.0

2 release files

0.42.0

2 release files

0.41.0

2 release files

0.40.0

2 release files

0.39.0

2 release files

0.29.0

2 release files

0.28.0

2 release files

0.27.0

2 release files

0.26.0

2 release files

0.25.0

2 release files

0.24.0

2 release files

0.23.0

2 release files

0.22.0

2 release files

0.21.0

2 release files

0.20.0

2 release files

0.19.0

2 release files

0.18.0

2 release files

0.17.0

2 release files

0.16.0

2 release files

0.15.0

2 release files

0.14.0

2 release files

0.13.0

2 release files

0.12.0

2 release files

0.9.0

2 release files

0.8.0

2 release files

0.7.0

2 release files

0.6.1

2 release files

0.6.0

2 release files

0.5.0

2 release files

0.4.0

2 release files

0.3.1

2 release files

0.3.0

2 release files

0.2.1

2 release files

0.2.0

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page