List of all the App Engine images service get_serving_url() URI options

In response to another question, a commenter mentioned an undocumented URI option I was not aware of to flip images horizontally/vertically with the App Engine images service.

The documentation mentions a few basic options:

  • =s0 — fullsize
  • =s640 — longest edge 640px long
  • =s640-c — 640px square

Would be nice to generate a comprehensive list of options, or if someone could provide any more options they know about here to serve as de facto documentation.


Between reading some random posts and manually doing some investigative research, I have put together the following list. Please drop any other knowledge in other answers or in comments and I can integrate it here.

Usage Example

We can effect various image transformations by tacking strings onto the end of an App Engine blob-based image URL, following an = character. Options can be combined by separating them with hyphens, eg.:

http://[image-url]=s200-fh-p-b10-c0xFFFF0000

or:

http://[image-url]=s200-r90-cc-c0xFF00FF00-fSoften=1,20,0:

... which have the following effect (documentation below):

As an example of how awesome this is, here's an animated GIF, downsized and inverted:

… which we can then convert into an MP4 video with one extra parameter: click to see MP4 version


SIZE / CROP

  • s640 — generates image 640 pixels on largest dimension
  • s0 — original size image
  • w100 — generates image 100 pixels wide
  • h100 — generates image 100 pixels tall
  • s (without a value) — stretches image to fit dimensions
  • c — crops image to provided dimensions
  • n — same as c, but crops from the center
  • p — smart square crop, attempts cropping to faces
  • pp — alternate smart square crop, does not cut off faces (?)
  • cc — generates a circularly cropped image
  • ci — square crop to smallest of: width, height, or specified =s parameter
  • nu — no-upscaling. Disables resizing an image to larger than its original resolution.

PAN AND ZOOM

  • x, y, z: — pan and zoom a tiled image. These have no effect on an untiled image or without an authorization parameter of some form (see googleartproject.com).

ROTATION

  • fv — flip vertically
  • fh — flip horizontally
  • r{90, 180, 270} — rotates image 90, 180, or 270 degrees clockwise

IMAGE FORMAT

  • rj — forces the resulting image to be JPG
  • rp — forces the resulting image to be PNG
  • rw — forces the resulting image to be WebP
  • rg — forces the resulting image to be GIF

  • v{0,1,2,3} — sets image to a different format option (works with JPG and WebP)

Forcing PNG, WebP and GIF outputs can work in combination with circular crops for a transparent background. Forcing JPG can be combined with border color to fill in backgrounds in transparent images.

ANIMATED GIFs

  • rh — generates an MP4 from the input image
  • k — kill animation (generates static image)

MISC.

  • b10 — add a 10px border to image
  • c0xAARRGGBB — set border color, eg. =c0xffff0000 for red
  • d — adds header to cause browser download
  • e7 — set cache-control max-age header on response to 7 days
  • l100 — sets JPEG quality to 100% (1-100)
  • h — responds with an HTML page containing the image
  • g — responds with XML used by Google's pan/zoom

Filters

  • fSoften=1,100,0: - where 100 can go from 0 to 100 to blur the image
  • fVignette=1,100,1.4,0,000000 where 100 controls the size of the gradient and 000000 is RRGGBB of the color of the border shadow
  • fInvert=0,1 inverts the image regardless of the value provided
  • fbw=0,1 makes the image black and white regardless of the value provided

Unknown Parameters

These parameters have been seen in use, but their effect is unknown: no, nd, mv

Caveats

Some options (like =l for JPEG quality) do not seem to generate new images. If you change another option (size, etc.) and change the l value, the quality change should be visible. Some options also don't work well together. This is all undocumented by Google, probably with good reason.

Moreover, it's probably not a good idea to depend on any of these options existing forever. Google could remove most of them without notice at any time.


I was browsing through stuff one day, and then I actually found a javascript asset on one of google's pages that had the English variable names and their types! Here's a nicely formatted version I made:

int:  s   ==> Size
int:  w   ==> Width
bool: c   ==> Crop
hex:  c   ==> BorderColor
bool: d   ==> Download
int:  h   ==> Height
bool: s   ==> Stretch
bool: h   ==> Html
bool: p   ==> SmartCrop
bool: pa  ==> PreserveAspectRatio
bool: pd  ==> Pad
bool: pp  ==> SmartCropNoClip
bool: pf  ==> SmartCropUseFace
int:  p   ==> FocalPlane
bool: n   ==> CenterCrop
int:  r   ==> Rotate
bool: r   ==> SkipRefererCheck
bool: fh  ==> HorizontalFlip
bool: fv  ==> VerticalFlip
bool: cc  ==> CircleCrop
bool: ci  ==> ImageCrop
bool: o   ==> Overlay
str:  o   ==> EncodedObjectId
str:  j   ==> EncodedFrameId
int:  x   ==> TileX
int:  y   ==> TileY
int:  z   ==> TileZoom
bool: g   ==> TileGeneration
bool: fg  ==> ForceTileGeneration
bool: ft  ==> ForceTransformation
int:  e   ==> ExpirationTime
str:  f   ==> ImageFilter
bool: k   ==> KillAnimation
int:  k   ==> FocusBlur
bool: u   ==> Unfiltered
bool: ut  ==> UnfilteredWithTransforms
bool: i   ==> IncludeMetadata
bool: ip  ==> IncludePublicMetadata
bool: a   ==> EsPortraitApprovedOnly
int:  a   ==> SelectFrameint
int:  m   ==> VideoFormat
int:  vb  ==> VideoBegin
int:  vl  ==> VideoLength
bool: lf  ==> LooseFaceCrop
bool: mv  ==> MatchVersion
bool: id  ==> ImageDigest
int:  ic  ==> InternalClient
bool: b   ==> BypassTakedown
int:  b   ==> BorderSize
str:  t   ==> Token
str:  nt0 ==> VersionedToken
bool: rw  ==> RequestWebp
bool: rwu ==> RequestWebpUnlessMaybeTransparent
bool: rwa ==> RequestAnimatedWebp
bool: nw  ==> NoWebp
bool: rh  ==> RequestH264
bool: nc  ==> NoCorrectExifOrientation
bool: nd  ==> NoDefaultImage
bool: no  ==> NoOverlay
str:  q   ==> QueryString
bool: ns  ==> NoSilhouette
int:  l   ==> QualityLevel
int:  v   ==> QualityBucket
bool: nu  ==> NoUpscale
bool: rj  ==> RequestJpeg
bool: rp  ==> RequestPng
bool: rg  ==> RequestGif
bool: pg  ==> TilePyramidAsProto
bool: mo  ==> Monogram
bool: al  ==> Autoloop
int:  iv  ==> ImageVersion
int:  pi  ==> PitchDegrees
int:  ya  ==> YawDegrees
int:  ro  ==> RollDegrees
int:  fo  ==> FovDegrees
bool: df  ==> DetectFaces
str:  mm  ==> VideoMultiFormat
bool: sg  ==> StripGoogleData
bool: gd  ==> PreserveGoogleData
bool: fm  ==> ForceMonogram
int:  ba  ==> Badge
int:  br  ==> BorderRadius
hex:  bc  ==> BackgroundColor
hex:  pc  ==> PadColor
hex:  sc  ==> SubstitutionColor
bool: dv  ==> DownloadVideo
bool: md  ==> MonogramDogfood
int:  cp  ==> ColorProfile
bool: sm  ==> StripMetadata
int:  cv  ==> FaceCropVersion

Notes:

  • bool means just add the variable by itself
  • int means number after variable name
  • string means (potentially complex) string after variable name
  • hex means hexidecimal number in format 0x000000 after variable name
  • variables are separated by hyphens (-)

Detailed v option investigation

How I discovered it

I found out the v option really unintentionally!

Someday, while I was investigating the image response headers, I found an attribute etag with value set to v1. Since I haven't seen any v option yet, I just tried adding it to the image url and it worked! Despite the header attribute value probably has nothing to do with the v option, it helped me to accidentally find it.

Investigating how the effect works

First, I've noticed that setting v0 and not setting v resulted in the same response, which indicates that v0 returns the original image with no v option (just like using s0 on the s option would return the original sizing).

Then, I've noticed that setting v1, v2, and v3 progressively returned an image with a smaller content size (weight), and visually it became poorer. Interestingly, setting v4, v5, etc, didn't continue to optimize it.

Investigating what the effect is

Some other day I tested the same parameters on another image, and found that nothing happened. That was interesting: an option that works for an image and doesn't work for another, so I started testing what was the difference between the images. Reviewing the list of parameters, it came to me that it could be the image type, and indeed it was! The first image type I've tried the v option was JPEG, and the second was PNG. So, I could reproduce the same effect by setting the second one with both rj and v3!

Hence, I searched internet about JPEG types, and interestingly I've found some sources (as you can see here, and here) explaining about 3 types of JPEG: Baseline Standard, Baseline Optimized, and Progressive, perfectly fitting the three variations available within the v options!

Investigating when the effect works

I went trying the same v option on other image types, and found that WebP also supported the same kind of customized type, also progressively optimizing the image in weight and quality (but much lesser in quality than JPEG) in the same range between v0 and v3. Unfortunately, I haven't yet found any sources of different WebP types.

Also, it didn't change anything when used on GIFs, but, as the PNG type, you can also combine its options with rj and v3, but you would (of course) lose the GIF animation and quality.


As sad as it makes me to tell you, I don't think, unless you are in Google, that this documentation is public-facing :(.

Developers.google.com is FILLED with stuff, but not always comprehensive/easy to find/understand. Until Google builds a public-facing tool, we have to work with what we have.