GBIF's API Returns CC BY-NC Images by Default, Which Breaks Commercial Use
GBIF is one of the better open data APIs. No key, no registration, generous limits, and well over a billion species occurrence records, a large share of them carrying photographs. It is an obvious source if you need images of living things and you do not want to pay a stock library.
There is a trap in the default response, and it is the kind that does not surface until someone sends you a letter.
What the Default Gives You
A plain image query looks like this:
https://api.gbif.org/v1/occurrence/search?scientificName=Ophrys%20apifera&mediaType=StillImage&limit=5
Records come back with a license field. Run that query and a large proportion of what you get is:
http://creativecommons.org/licenses/by-nc/4.0/legalcode
That is CC BY-NC. Non-commercial. A big share of GBIF’s photographic material originates on iNaturalist, where BY-NC is the most common licence users pick, so it dominates the default ordering.
If your site carries advertising, sells anything, promotes a business, or exists as part of a commercial portfolio, BY-NC images are not available to you. The definition of non-commercial in the licence is broader than most developers assume, and “it’s only a blog” is not a defence anyone wants to test.
Filtering Properly
Pass license and repeat it for each acceptable value. GBIF treats repeated parameters as OR:
https://api.gbif.org/v1/occurrence/search
?scientificName=Masdevallia%20veitchiana
&mediaType=StillImage
&license=CC0_1_0
&license=CC_BY_4_0
&limit=20
The enum values you want are CC0_1_0 and CC_BY_4_0. The one to exclude is CC_BY_NC_4_0. There are also records with UNSPECIFIED or UNSUPPORTED, which you should treat as unusable rather than as permission.
Expect the result count to collapse. In testing across several orchid species, the drop ran from 241 records to 21, from 245 to 16, and in one case from 48 to zero. A species can be well documented and still have no image you are allowed to publish.
Build your pipeline to handle the zero case rather than assuming every species yields a picture.
CC BY Still Needs a Credit
CC0_1_0 is a public domain dedication and carries no attribution requirement. CC_BY_4_0 does. If you accept both in the same query you have to attribute at least some of what comes back, so the simplest approach is to attribute all of it and stop tracking which is which.
The fields to pull for a credit line are rightsHolder, recordedBy, and license. A caption of the form “Photo: Name, via GBIF (CC BY 4.0)” satisfies the licence and costs you one line of template.
An Unrelated Gotcha While You Are Here
Higher taxon filters do not work the way the parameter name suggests. This:
https://api.gbif.org/v1/occurrence/search?genus=Dracula&limit=4
does not filter to the genus Dracula. It returns the full unfiltered index, tens of millions of records, silently. There is no error.
GBIF wants a numeric key. Resolve the name first:
https://api.gbif.org/v1/species/match?name=Dracula&rank=GENUS
Take usageKey from that response and pass it as genusKey:
https://api.gbif.org/v1/occurrence/search?genusKey=NNNNNNN&limit=4
The same applies to familyKey, taxonKey and the rest. Any time a taxon filter appears to do nothing, check whether you are passing a name where a key belongs, and sanity-check the returned count against what you expect. A count in the tens of millions means your filter was ignored.
Practical Defaults
Filter licences server-side rather than fetching broadly and discarding, because the ordering means an unfiltered page of results may contain nothing usable at all. Store the licence string alongside every image you cache, since you will not remember later which pictures came with obligations. And treat the media URLs as what they are, which is links to third-party hosts like iNaturalist’s S3 bucket or an institutional IIIF server, not a CDN with any promise of stability.