Fetch and Display Behance Portfolio Projects Using the Behance API
Learn how to fetch a Behance user’s projects with the public API, parse the JSON, render clickable thumbnails, handle pagination, and implement basic error recovery.
13 Jul 2025, 18:16 UTC

Desired Outcome
Retrieve a Behance user’s portfolio projects via the public API and render them as clickable thumbnails on a web page, with basic pagination handling and graceful error recovery.
Prerequisites
- A Behance account.
- Access to the Behance Developer Portal to create an application and obtain a public API key.
- A development environment capable of running a local web server (e.g., Node.js with
http-server, Python’shttp.server, or any static‑file server). - Basic familiarity with HTML, JavaScript (ES6+), and making HTTP requests from the browser.
Procedure
1. Obtain the API key
Log in to the Behance Developer Portal, click “Create an Application”, fill in the required fields, and note the generated Public API Key. Treat this key as a secret; it should never be committed to a public repository.
2. Identify the target user ID
Every Behance user has a numeric user_id. You can find it by visiting the user’s profile page and looking at the URL (e.g., https://www.behance.net/12345678) or by using the /users search endpoint.
3. Construct the request URL
The endpoint for a user’s projects is:
https://api.behance.net/v2/users/{user_id}/projects?api_key={YOUR_API_KEY}&page={PAGE}&per_page={PER_PAGE}
{user_id}– the numeric ID from step 2.{YOUR_API_KEY}– the public key from step 1.{PAGE}– starting at 1; increment to fetch subsequent pages.{PER_PAGE}– number of projects per request (Behance allows up to 20; larger values increase payload size).
4. Make the request from the browser
Use the Fetch API (or XMLHttpRequest) to call the endpoint. Below is a minimal example that logs the raw JSON response to the console.
async function fetchBehanceProjects(userId, apiKey, page = 1, perPage = 20) {
const url = `https://api.behance.net/v2/users/${userId}/projects?api_key=${apiKey}&page=${page}&per_page=${perPage}`;
try {
const response = await fetch(url);
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
const data = await response.json();
return data;
} catch (err) {
console.error('Behance API request failed:', err);
return null;
}
}
// Example usage
fetchBehanceProjects('12345678', 'YOUR_PUBLIC_API_KEY')
.then(result => {
if (result) console.log(result);
});
5. Parse the JSON response
A successful response contains:
data– an array of project objects.pagination– an object withpage,pages, andtotal.
Each project object includes at least:
title– string.url– link to the project on Behance.images– object withthumbnailURLs (e.g.,images['230']for a 230‑px wide thumbnail).created_on– Unix timestamp.
6. Render the projects
Iterate over data and create thumbnail elements that link to the project page.
function renderProjects(projects) {
const container = document.getElementById('behance-gallery');
container.innerHTML = ''; // clear previous content
projects.forEach(proj => {
const thumbUrl = proj.images?.['230'] || proj.images?.['130'] || '';
const link = document.createElement('a');
link.href = proj.url;
link.target = '_blank';
link.rel = 'noopener';
const img = document.createElement('img');
img.src = thumbUrl;
img.alt = proj.title;
img.loading = 'lazy';
link.appendChild(img);
container.appendChild(link);
});
}
// Integrating fetch and render
async function loadAndShow(page = 1) {
const data = await fetchBehanceProjects('12345678', 'YOUR_PUBLIC_API_KEY', page, 12);
if (data && data.data) {
renderProjects(data.data);
// Store pagination info for next/prev buttons
window.behancePagination = data.pagination;
} else {
document.getElementById('behance-gallery').innerHTML =
'Unable to load projects at this time.
';
}
}
// Initial load
loadAndShow(1);
7. Handle pagination
Use the pagination object to enable “Next” and “Previous” buttons:
function setupPagination() {
const prevBtn = document.getElementById('prev-page');
const nextBtn = document.getElementById('next-page');
prevBtn.disabled = true;
nextBtn.disabled = true;
prevBtn.addEventListener('click', () => {
if (window.behancePagination.page > 1) {
loadAndShow(window.behancePagination.page - 1);
}
});
nextBtn.addEventListener('click', () => {
if (window.behancePagination.page < window.behancePagination.pages) {
loadAndShow(window.behancePagination.page + 1);
}
});
}
// Call after first load
loadAndShow(1).then(() => {
if (window.behancePagination) {
setupPagination();
}
});
8. Basic error recovery and rate‑limit handling
- If the response status is
429(Too Many Requests), retry after a delay using exponential back‑off (e.g., 1 s, 2 s, 4 s, …) up to a maximum of three attempts. - For network errors or non‑JSON responses, display a user‑friendly placeholder and log the error for developers.
- Validate required fields before accessing them (e.g.,
if (proj.images && proj.images['230']) { … }) to avoid runtime errors if the API schema changes.
Expected Checks
- Open the browser’s developer console and verify that a
200 OKresponse is logged for the initial request. - Confirm that the
dataarray contains at least one project object and that each object hastitle,url, and an image thumbnail URL. - Visually inspect the page: thumbnails should appear, be clickable, and open the corresponding Behance project in a new tab.
- Click the “Next” button and observe that the request URL’s
pageparameter increments and new thumbnails load. - Simulate a rate‑limit by sending rapid requests (e.g., via
setIntervalwith a 100 ms interval) and ensure the client shows a retry message or disables further requests until the back‑off completes.
Recovery Options
If the API is temporarily unavailable or returns an error:
- Show a static placeholder image or a message such as “Unable to load Behance portfolio – please try again later.”
- Optionally cache the last successful response in
localStorageand display the cached data while waiting for a fresh fetch. - Provide a manual “Retry” button that re‑invokes
loadAndShow.