Product downloads
Every CodeAndWeb app has a download URL that never changes. Ask for
https://www.codeandweb.com/download/texturepacker/latest/mac and you get the installer of the
newest stable release, whatever that happens to be today.
This page is for the scripts rather than for the people: a Dockerfile, an install script, a Windows or Linux packager, an agent fetching a build. Anything that wants the current installer without parsing an XML feed that was designed for the macOS updater. If you are here to install one of our apps on your own machine, the per-product download pages are the friendlier place to be, and they are linked from every row of the table below.
Current downloads
TexturePacker
Version 8.3.0
Install helpRelease noteslatest.json
- Linux (.deb)
- /download/texturepacker/latest/linux-deb
- Linux (Flatpak)
- /download/texturepacker/latest/linux-flatpak
TexturePacker 3D
Version 1.2.4
Install helpRelease noteslatest.json
PhysicsEditor
Version 2.1.0
Install helpRelease noteslatest.json
- Linux (.deb)
- /download/physicseditor/latest/linux-deb
SpriteIlluminator
Version 2.2.0
Install helpRelease noteslatest.json
- Linux (.deb)
- /download/spriteilluminator/latest/linux-deb
BabelEdit
Version 5.7.0
Install helpRelease noteslatest.json
- Linux (.deb)
- /download/babeledit/latest/linux-deb
- Linux (Flatpak)
- /download/babeledit/latest/linux-flatpak
| Product | Platform | Links |
|---|---|---|
| TexturePacker8.3.0 |
| |
| TexturePacker 3D1.2.4 | ||
| PhysicsEditor2.1.0 | ||
| SpriteIlluminator2.2.0 | ||
| BabelEdit5.7.0 |
|
These are the current stable releases. The page is rebuilt whenever a release ships, so the version numbers are as fresh as the last build of this site, on October 12, 2026. The /latest/ URLs above are always live: they redirect to the newest installer at the moment you request them, even when this table is a day behind.
The URL pattern
https://www.codeandweb.com/download/<product>/latest/<platform>The product is one of texturepacker, texturepacker3d, physicseditor, spriteilluminator or
babeledit. The platform is one of the tokens below. Both are case-insensitive, so
/download/TexturePacker/latest/Mac works exactly like the lowercase form.
The URL answers with a 302 to the versioned installer, so the file you end up with still carries
its version in the name. The 302 also carries an X-Latest-Version header, which is the cheapest
way to find out what the URL currently points at from a shell:
curl -fsSI https://www.codeandweb.com/download/texturepacker/latest/mac | grep -i x-latest-versionFrom a browser, read the version out of the manifest instead. A cross-origin fetch() of this
URL does not work at all: with the default redirect: "follow" the browser re-runs the CORS check
against the installer the 302 points at, that file is served straight off disk without an
Access-Control-Allow-Origin header, and the whole call rejects with a TypeError rather than
returning anything you can read. With redirect: "manual" you get an opaque response whose headers
are unreadable by definition, so X-Latest-Version is out of reach either way. The manifest below
is not a redirect, so its version is readable from a browser like any other JSON field.
Both /latest and /latest/ serve the manifest, and both will keep doing so. Prefer the form
without the trailing slash: it is the one every example here uses, and picking one spelling keeps
you off a second cache entry for the same document.
Platform tokens
| Platform | Token | Also accepted | Gets you |
|---|---|---|---|
| macOS | mac | macososxdarwin | .dmg |
| Windows | windows | win | .msi |
| Linux (.deb) | linux-deb | debubuntulinux | .deb |
| Linux (Flatpak) | linux-flatpak | flatpak | .flatpak |
Not every app ships every platform. TexturePacker3D has no Linux build at all, and PhysicsEditor and
SpriteIlluminator ship no Flatpak, so those three apps list fewer platforms in the downloads table at
the top of this page. Asking for a platform we do not build returns a 404 that names the platforms
that app does have.
The manifests
If you would rather resolve the version yourself than follow a redirect, every app publishes a small JSON manifest:
https://www.codeandweb.com/download/<product>/latest.json{
"schemaVersion": 1,
"product": "TexturePacker",
"slug": "texturepacker",
"version": "8.3.0",
"released": "2026-09-16",
"releaseNotes": "https://www.codeandweb.com/texturepacker/download",
"downloads": {
"mac": {
"version": "8.3.0",
"released": "2026-09-16",
"url": "https://www.codeandweb.com/download/texturepacker/8.3.0/TexturePacker-8.3.0.dmg",
"latestUrl": "https://www.codeandweb.com/download/texturepacker/latest/mac",
"fileName": "TexturePacker-8.3.0.dmg",
"size": 70131770,
"sha256": "77891a9afa52c0e67cb26f7bb915b3e3ee77a9558a77681e69d1e7545eae782d",
"ed25519": "qkdi3cpiEwIpI0b0UFtbdoVdOBttzvDrqCv134q73JoNyyFpdOk8EotHFGroNFxveSIrVweiXtAeeo7BsuMyAw=="
}
}
}url is the immutable, versioned installer. latestUrl is the floating URL from the section above.
A platform we do not build is left out of downloads entirely rather than being present with a
null, and sha256 or ed25519 can be missing for an older build, so read them defensively.
ed25519 is the same EdDSA signature the appcast carries. See
checking what you downloaded for what to do with it.
All five apps in one document:
https://www.codeandweb.com/download/latest.jsonThat one wraps the same per-app manifests in a products array. If one app's release data cannot be
read, that app drops out of the array and the other four still answer.
Manifests and redirects are both sent with Cache-Control: max-age=60, public and
Access-Control-Allow-Origin: *, so the manifests are readable from a browser as well as from a
build script. The redirects are not: following one cross-origin puts the browser on the installer
file itself, which carries no such header, so fetch() rejects. Use the manifests from a browser
and the /latest/<platform> URLs from anything that is not one.
The Sparkle appcast
Every app publishes a Sparkle feed, and it covers all four platforms, not only macOS:
https://www.codeandweb.com/releases/<product>/updatecheck.php?o=maco takes mac, win or linux and defaults to Windows. ov=flatpak gets the Flatpak, bit=32
the last 32-bit build, lang=de localised release-notes links. Stable releases only, newest first,
each enclosure signed with sparkle:edSignature and sparkle:dsaSignature. This is the feed
Homebrew reads. There is also /releases/<product>/appcast-mac-release.xml, macOS only, no
parameters.
It differs from latest.json in two ways that matter. It stops at a version we set by hand, so
a release aimed at new installs can go onto the site without prompting existing customers to update
for features they did not ask for. And it honours minimum OS versions: pass the running system
as ov=12.0.0 and an old mac is offered the newest release it can actually run, which the latest
URLs never do.
Every build is scanned before we upload it
Every installer goes through VirusTotal before it reaches our
servers. VirusTotal addresses a file by its SHA-256, the same sha256 the manifest publishes, so
the report for any build is a URL you can assemble yourself:
https://www.virustotal.com/gui/file/<sha256>That scan describes the file when we published it. The sha256 is what proves the bytes you
downloaded are the ones we scanned, so verify it anyway.
Checking what you downloaded
Three ways, in the order most people should reach for them.
The code signature. Every installer is signed, and your operating system already knows how to check it. No key from us, nothing to pin. On macOS the signature is a notarized Developer ID:
spctl -a -vvv -t install /Applications/TexturePacker.app
# source=Notarized Developer ID
# origin=Developer ID Application: CodeAndWeb GmbH (8P8584JRFS)On Windows the installer carries an extended-validation certificate issued to CodeAndWeb GmbH:
(Get-AuthenticodeSignature .\TexturePacker-8.3.0.msi).Status
(Get-AuthenticodeSignature .\TexturePacker-8.3.0.msi).SignerCertificate.Subject
# Valid
# CN=CodeAndWeb GmbH, O=CodeAndWeb GmbH, L=Neu-Ulm, S=Bavaria, C=DEThe sha256. For a build machine, pin the versioned url and its sha256 and compare after
downloading, as in the CI recipe below. That catches a truncated or swapped
file.
The ed25519 signature. The checksum sits on the same server as the installer, so it cannot
tell you that server was not compromised. The signing key is not on it, so the signature can. Our
public key, the same one Sparkle uses and the same one already inside every app you have installed:
jN2H7aeSZm8Y3vFbDpD80J5pXpnzfJNq5+Uqj5ryUAI=Pin that value in your build. Checking a signature against a key you fetched in the same breath proves nothing. Then, with OpenSSL 3:
printf '\x30\x2a\x30\x05\x06\x03\x2b\x65\x70\x03\x21\x00' > key.der
echo "jN2H7aeSZm8Y3vFbDpD80J5pXpnzfJNq5+Uqj5ryUAI=" | base64 -d >> key.der
openssl pkey -pubin -inform DER -in key.der -out key.pem
echo "tmlJXdT9EDV5itPc4RwelMiegDwJQntsv7wMw3Hh3uNXiOcgHda4wLHsguSUhlFTo8rLXPoMcseYtiWx/etTDA==" | base64 -d > sig.bin
openssl pkeyutl -verify -pubin -inkey key.pem -rawin -in TexturePacker-8.3.0.msi -sigfile sig.bin
# Signature Verified SuccessfullyThose twelve bytes are the DER header for an Ed25519 public key: Sparkle publishes the bare 32-byte
key and OpenSSL wants it wrapped. Note the macOS system openssl is LibreSSL and cannot do this;
use OpenSSL 3 or any language binding.
Using the URLs in a script
Every example below uses curl -fL, and the -f is not decoration. Without it curl treats an HTTP
error as success: curl -sLO .../latest/mac against a 404 exits 0 and writes the error page to
disk as a file called mac. With -f it exits non-zero and writes nothing. Test for failure, not
for a particular exit code: it is 56 over HTTP/2 and 22 over HTTP/1.1.
-O is the other trap. It names the file after the URL you typed, not the redirect target, so
/latest/mac saves a file called mac. Browsers and wget keep the versioned name, curl -O does
not. Use -o. The one safe place for -O is the pinned CI recipe below, where the URL already ends
in the file name.
In CI: resolve, verify, pin
This is the workflow we would run in a build. Read the manifest once, commit the immutable url and
its sha256, and let the build fetch that exact file:
# once, by hand: read "url" and "sha256" out of the manifest
curl -fsSL https://www.codeandweb.com/download/texturepacker/latest.json
# in the build, with the committed values:
curl -fLO "$TP_URL" && echo "$TP_SHA256 $(basename "$TP_URL")" | sha256sum -cThe build is now reproducible, a tampered file fails the checksum, and upgrading is a visible commit rather than something that happens to you on a Tuesday.
The sha256 belongs to url, not to latestUrl. Read the checksum from the manifest and then
fetch latestUrl, and a release landing between those two calls looks exactly like a corrupted
download. If you want to follow latest, skip the checksum. If you want the checksum, pin the url
it came with.
On your own machine: follow latest
For an evaluation, a developer laptop or a throwaway container, following the floating URL is the whole point of it:
curl -fL -o TexturePacker.dmg https://www.codeandweb.com/download/texturepacker/latest/macPowerShell
Invoke-WebRequest follows the redirect and fails on an HTTP error on its own, writing nothing to
disk, so it needs no equivalent of -f. Do not expect the error to name the status though: against
our 404s .NET cannot read the error body and reports
WebException: The request was aborted: The connection was closed unexpectedly. Test for failure,
not for a message.
Invoke-WebRequest -Uri https://www.codeandweb.com/download/texturepacker/latest/windows -OutFile TexturePacker.msiResolve, verify and pin looks like this:
# once, by hand: read the values out of the manifest
$manifest = Invoke-RestMethod https://www.codeandweb.com/download/texturepacker/latest.json
$manifest.downloads.windows.url
$manifest.downloads.windows.sha256
# in the build, with the committed values:
Invoke-WebRequest -Uri $env:TP_URL -OutFile TexturePacker.msi
if ((Get-FileHash TexturePacker.msi -Algorithm SHA256).Hash -ne $env:TP_SHA256) {
throw "TexturePacker.msi does not match the published checksum"
}Get-FileHash returns upper-case hex and the manifest publishes lower case. -ne compares
case-insensitively, so the line above is right as written. Change it to -cne, or port it to a
language that compares bytes, and it fails on every build.
Things to watch out for
Docker caches the layer, not the answer
Docker caches a RUN line by its text alone, and the text of a version-less URL never changes. So a
RUN curl .../latest/... layer keeps installing the build it downloaded the first time, months after
the redirect moved on. This is the single most common surprise with a floating URL. Prefer ADD with
the URL, and when you need the certainty, build with --no-cache or bump a --build-arg that the
download line depends on.
Bare linux means Debian packaging
linux is an alias for linux-deb, so it gives you a .deb. That is invisible to somebody on
Fedora or Arch who reasonably expected "the Linux build". Ask for linux-flatpak if you want the
distro-independent package, and see the table above for which apps have one.
A platform can be retired
A platform token resolves to the newest stable release that shipped that platform, which is not
always the newest release. So if we stopped building a .deb, /latest/linux-deb would keep handing
you the last one we built, indefinitely and without an error. It will never give you a different
package format, but it can silently stop moving.
A 404 means something narrower: we have never shipped that platform for that app, which is why
/download/physicseditor/latest/linux-flatpak is a 404 today.
To catch a platform that has stopped moving, watch its per-platform version in latest.json. One
release of lag proves nothing, since a release can ship without every platform, but one that stays
behind over several releases is no longer being built.
The minimum OS version is not expressed
The in-app updater offers every system the newest release it can run. The latest URLs know nothing
about that: they always resolve to the newest stable release. A macOS 12 user who runs the curl line
above gets 8.3.0, which may need a newer system. For an older system, take the version from
the product's FAQ entry, for example TexturePacker.
A license covers a date range, not a version range
Single User and Volume licenses are perpetual and cover every release, major or minor, published
inside their update window: twelve months from purchase, or forever with a Lifetime license. So a
major version jump is not itself the problem. A build published after that window closed is, and
following latest is a good way to meet one without noticing.
Those licenses also do not permit use on a server or in an automated build at all. The floating
Docker/CI license does, and it always permits the newest version, which is what makes it the right
one to put behind a latest URL. See
Docker and CI installation.
Reserved, and not available today
These shapes are reserved so the contract can grow without breaking. All of them return 404
right now. Do not write them into a script expecting them to start working:
| Shape | Intended for |
|---|---|
mac-arm64, mac-x64 | separate Apple Silicon and Intel builds, if we ever stop shipping universal binaries |
/download/<product>/beta/<platform> | the newest beta instead of the newest stable |
/download/<product>/<major>/latest/<platform> | the newest release within one major version |
win64 is deliberately not a token and will keep returning 404. A URL with "64" in the name
must never be able to hand somebody a 32-bit build, and the windows token resolves to whichever
Windows build a release actually carries.
Package managers
Homebrew already tracks TexturePacker and BabelEdit through the Sparkle appcast
and computes its own checksums, so nothing here changes for brew install. Chocolatey and winget have
nothing, because neither of them speaks Sparkle. That is the gap these URLs exist to close, and it is
a format gap rather than a platform one: the appcast has carried Windows and Linux builds for years,
but only in an RSS dialect written for one updater framework.