GunSpec
Media & drawings

Media & drawings

Every firearm carries a line-art silhouette, every cartridge a scale illustration, every load a bullet diagram, and a growing share of the catalog a photograph, a schematic or a 3D model. This page shows how each is made, what it is drawn from and how to fetch it. The drawings below are produced by the same code the website and the API use, from the same records.

  • 2,589Silhouettes
  • 605Cartridges drawn
  • 16Fields a cartridge is drawn from
  • 8Bullet profiles

Five kinds, one shape. GET /v1/firearms/{id}/media lists everything a firearm has as one array, each item tagged with its kind, and /media/{selector} fetches one by that kind without a prior lookup.

KindWhat it isHow it is madeCoverage
silhouetteA scalable black line-art profile of the firearm, sized to its real dimensions.Drawn from a reference photograph by an image model, cleaned, cropped and traced to vector paths.2,589 of 9,162 firearms; every new record gets one.
renderA generated studio-style image of the firearm.Image model from the reference photograph; background removed.Where a usable reference exists.
photoA photograph, with its source and licence.Curated from manufacturer material and licensed archives; never scraped from a shop.Growing; listed by /v1/firearms/media.
schematicAn exploded view or technical drawing.Manufacturer and archival documents, credited to their source.Where the maker publishes one.
modelA glTF binary ready for three.js or Babylon.Optimised from source models: meshopt compression, WebP textures, quantised meshes.A curated set; filter with has_3d_model=true.

2,589 firearms have a line-art silhouette. These four are the exact files the website renders, loaded from this page's own bundle; on the dark theme they are inverted, as the website inverts them.

  1. 1A reference photograph is normalised: flattened, converted to sRGB, resized. Photographs that fail moderation fall back to a text-only generation and are marked as such.
  2. 2An image model draws bold black-on-white line art of the subject alone, no background. A prompt that asks for a filled silhouette gives a blob; the pipeline asks for line art and fills it afterwards.
  3. 3The result is cleaned in one pass: background to transparent, tight crop, anti-alias halo mapped to alpha so no light ring survives on a dark page.
  4. 4The bitmap is traced to vector paths with VTracer at zero dilation, so lines keep their drawn weight. The output is a solid-fill SVG, not a stroke outline.
  5. 5The file is recorded on the firearm as svgLineArtUrl, uploaded to the asset CDN, and served through the API with the stroke colour and width you ask for.

On the website the same file is served obfuscated and decoded client-side, which is why an API caller receives an absolute CDN URL instead: a path no consumer could fetch was documented for a while as if they could. The field is in the field reference.

A cartridge is never drawn from its name. It is drawn from up to 16 fields on the caliber record: rim, base, shoulder and neck diameters, case and overall length, bullet length and diameter, head type, case shape, material, projectile kind, bullet profile, closure and marking colour. The six below are drawn on this page by the shared renderer from the record as it stands.

  • 9x19mm Parabellum14 of 16 drawing fields on the record95% confidenceheadrimlesscasetaperedprojectilebulletprofileround_noseclosurebullet
  • .45 ACP14 of 16 drawing fields on the record95% confidenceheadrimlesscasestraightprojectilebulletprofileround_noseclosurebullet
  • .223 Remington15 of 16 drawing fields on the record95% confidenceheadrimlesscasebottleneckprojectilebulletprofilespitzerclosurebullet
  • 7.62x39mm15 of 16 drawing fields on the record95% confidenceheadrimlesscasebottleneckprojectilebulletprofilespitzerclosurebullet
  • 12 Gauge12 of 16 drawing fields on the record70% confidenceheadrimmedcasestraightprojectileshotclosurefold_crimp
  • .50 BMG15 of 16 drawing fields on the record90% confidenceheadrimlesscasebottleneckprojectilebulletprofilespitzerclosurebullet
  1. 1resolveCartridgeGeometry turns the record into drawable millimetres. Every figure the record carries is used as-is; a missing one is filled from ratio heuristics field by field, and the geometry says which were guessed.
  2. 2The case outline is built from head type and case shape, the projectile from profile and kind, then crimps, wads or pellets from the closure. projectile_kind: none is a blank and draws as one.
  3. 3Materials become gradients: brass is brass, lacquered steel is lacquered steel, a paper hull is paper. The marking colour is painted where the record says it belongs.
  4. 4Both renderers, the inline glyph and the measured chart, draw from the same geometry, so a caliber cannot look different on two pages.

The closed vocabularies a cartridge is drawn from

caseShapeCase profile: straight, bottleneck, tapered, belted.
straight, tapered, bottleneck, none
caseMaterialWhat the case is made of: brass, steel, aluminium, polymer.
brass, nickel_brass, steel, lacquered_steel, aluminium, polymer, paper, caseless, none
projectileKindnone is a blank.
bullet, none, shot, slug, round_ball, flechette, dart, pellet, rocket, grenade, signal
bulletProfileBullet shape: fmj, hollow_point, soft_point, spitzer, round_nose.
spitzer, spitzer_boat_tail, round_nose, flat_nose, wadcutter, semi_wadcutter, hollow_point, truncated_cone, round_ball
closureWhat seals the case mouth; a blank is a star crimp.
bullet, star_crimp, rosette_crimp, roll_crimp, fold_crimp, wad, paper, none
markingColorPaint that identifies the load: crimp lacquer on a blank, tip colour on a military round.
black, white, red, orange, yellow, green, blue, purple, pink, brown, grey, silver, gold

The figures come from the maker's or a standards body's published drawing and carry a confidence score like any record. Every cartridge is in the calibers reference with all of these fields.

A load's bullet_type is classified into one of 8 profiles and drawn as a side cross-section scaled to the caliber's bullet diameter. The API renders it on request at /v1/ammunition/{id}/bullet.svg; the rows below are that renderer's output for each profile at two diameters.

At 9 mm

  • Side profile of a FMJ bulletFMJ
  • Side profile of a JHP bulletJHP
  • Side profile of a AP bulletAP
  • Side profile of a SP bulletSP
  • Side profile of a OTM bulletOTM
  • Side profile of a Tracer bulletTracer
  • Side profile of a EPR bulletEPR
  • Side profile of a PT bulletPT

At 5.56 mm

  • Side profile of a FMJ bulletFMJ
  • Side profile of a JHP bulletJHP
  • Side profile of a AP bulletAP
  • Side profile of a SP bulletSP
  • Side profile of a OTM bulletOTM
  • Side profile of a Tracer bulletTracer
  • Side profile of a EPR bulletEPR
  • Side profile of a PT bulletPT
Fetch a bullet diagram
bash
# Public: no key neededcurl https://api.gunspec.io/v1/ammunition/m882/bullet.svg # Or straight into an img tag<img src="https://api.gunspec.io/v1/ammunition/m882/bullet.svg" alt="M882 Ball, side profile">

Rifle diameters get a longer body and a sharper ogive than pistol ones, so the same profile reads correctly across calibers. The endpoint needs no key. Every load in the ammunition reference carries its diagram URL as bulletSvgUrl.

The assets we host or link rather than draw. Each comes with the credit it needs to be reused.

  • Photographs and renders are indexed by GET /v1/firearms/media, a three-field row per firearm built for media grids and mirrors, with a fingerprint that changes when imagery is added or removed.
  • Schematics are exploded views and technical drawings from manufacturer and archival material, on Studio and above; the access matrix has the full gating.
  • 3D models are glTF binaries with meshopt compression, WebP textures and quantised meshes. A loader needs those three standard extensions and nothing else.
  • Assets we link rather than host answer with a 302 to their location; assets in our own bucket stream from the endpoint. Either way url on a media item is absolute and fetchable.

One resource for everything, plus the older per-kind routes, which remain. Addressing by kind needs no prior lookup; format=json returns the metadata without moving bytes, format=datauri inlines up to 256 KB.

EndpointReturnsPlan
/v1/firearms/{id}/mediaList every asset for a firearmapplication/jsonExplorer
/v1/firearms/{id}/media/{selector}Get one assetapplication/json, image/png, image/webp, image/jpeg, image/svg+xmlBuilder
/v1/firearms/mediaIndex every firearm that has imageryapplication/jsonExplorer
/v1/firearms/{id}/silhouetteGet silhouette line artapplication/json, image/svg+xmlBuilder
/v1/firearms/{id}/imagesList imagesapplication/jsonExplorer
/v1/firearms/{id}/images/{imageId}Get image assetapplication/json, image/png, image/webp, image/jpeg, image/svg+xmlBuilder
/v1/firearms/{id}/schematicsList schematicsapplication/jsonStudio
/v1/firearms/{id}/modelGet 3D modelmodel/gltf-binaryBuilder
/v1/ammunition/{id}/bullet.svgRender a bullet diagramimage/svg+xmlNo key
Three calls
bash
# Everything a firearm has, one shape, with a credit block per itemcurl -H "X-API-Key: your_api_key" \  https://api.gunspec.io/v1/firearms/ak-47/media # The silhouette as SVG, stroke recoloured, no prior lookupcurl -H "X-API-Key: your_api_key" \  "https://api.gunspec.io/v1/firearms/ak-47/media/silhouette?stroke_color=%23ffffff" # Just the metadata, no bytescurl -H "X-API-Key: your_api_key" \  "https://api.gunspec.io/v1/firearms/ak-47/media/photo?format=json"

Every media response carries an ETag and answers 304 when unchanged, so a mirror re-fetches nothing that did not move; see caching. A firearm gaining or losing an asset fires firearm.updated to webhook subscribers.

Every media item carries the attribution needed to reuse it, and every SVG the API serves is sandboxed before it reaches a browser.

The credit block on every item

credit.source
Where the record came from: a curated entry, an inference, or an import.
credit.author
Who made the asset, where it is credited.
credit.sourceUrl
Page the asset or document was taken from.
credit.license
Licence the asset is held under, where one is recorded.

How SVGs are served

An SVG can carry script. Every one the API serves, including silhouettes, bullet drawings and media, is sent with a Content-Security-Policy that stops it running anything if opened directly, and colour values written into a silhouette are validated and escaped. The policy, from the data protections page:

default-src
'none'
style-src
'unsafe-inline'
img-src
data:
sandbox