Question
I am downloading a JSON file from an online source. When my PHP script processes the data in a loop, it produces this error:
Fatal error: Maximum execution time of 30 seconds exceeded in C:\wamp\www\temp\fetch.php on line 24
What does this error mean, and how can I identify and fix the part of the download or loop that is taking too long?
Short Answer
You will learn how PHP execution time limits work, why a long-running loop or network request can exceed them, and how to diagnose the real bottleneck. You will also see safer solutions such as validating input, setting network timeouts, processing data in batches, and using pagination instead of only increasing the limit.
Concept
PHP applies a maximum execution time to prevent one request from running forever and consuming server resources. In many local PHP installations, the default value is 30 seconds.
When PHP reaches that limit, it stops the script and reports the file and line that was executing when time expired. The reported line is not always the original cause. For example, a slow HTTP download, an infinite loop, or expensive work inside an earlier loop iteration can make PHP eventually stop at line 24.
Common causes include:
- A loop that never reaches its stopping condition.
- A very large JSON response that takes a long time to download or decode.
- Repeated HTTP requests inside a loop.
- Slow database, file-system, or API operations inside a loop.
- Processing every record at once when the API supports pages or smaller batches.
Increasing the time limit can be appropriate for a known, intentional background task. However, it should not be the first fix: an accidental infinite loop will still run forever, only for longer.
Mental Model
Think of the PHP time limit as a timer on an exam.
- Your script is the student doing work.
- Each loop iteration is another question.
- Downloading data is waiting for a document to arrive.
- The execution limit is the exam bell.
If the document never arrives, or the student keeps answering the same question without moving forward, the bell rings. Giving the student more time helps only when there is genuinely more valid work to complete. It does not fix a student who is stuck on the same question.
Syntax and Examples
The configured limit is commonly set in php.ini:
max_execution_time = 30
For a specific script, PHP can request a different limit with set_time_limit():
<?php
set_time_limit(60); // Allow up to 60 seconds for this script.
for ($i = 1; $i <= 5; $i++) {
echo "Processing item {$i}\n";
}
You can inspect the configured value:
<?php
$limit = ini_get('max_execution_time');
echo "Maximum execution time: {$limit} seconds";
For remote JSON, set a network timeout as well. set_time_limit() controls PHP's script limit; a stream context controls how long an HTTP request may wait.
= ;
= ([
=> [
=> ,
],
]);
= (, , );
( === ) {
();
}
= (, , , JSON_THROW_ON_ERROR);
( ) {
}
Step by Step Execution
Consider this traceable example:
<?php
$items = [10, 20, 30];
$total = 0;
foreach ($items as $item) {
$total += $item;
}
echo $total;
Execution proceeds as follows:
$itemsis created with three values.$totalstarts at0.- First iteration:
$itemis10;$totalbecomes10. - Second iteration:
$itemis20;$totalbecomes30. - Third iteration:
$itemis30;$totalbecomes .
Real World Use Cases
Execution-time awareness matters whenever a request performs more than a small, immediate action:
- API imports: Download product, weather, or customer JSON from an external API.
- Data synchronization: Update local records from a remote service in batches.
- Report generation: Aggregate many rows before exporting CSV or PDF data.
- Image or file processing: Resize many uploads without blocking a web request too long.
- Admin tools: Import a spreadsheet while reporting errors for invalid rows.
For browser-triggered work, keep requests short where possible. Large imports are often better handled as scheduled command-line jobs or queue workers, where progress, retries, and logging are easier to manage.
Real Codebase Usage
In production code, developers usually address the source of slowness rather than placing one large timeout around everything.
Use guard clauses for failed downloads
<?php
$json = file_get_contents($url, false, $context);
if ($json === false) {
throw new RuntimeException('Remote API request failed.');
}
This prevents later code from trying to decode or loop over a failed response.
Validate JSON before processing
<?php
$data = json_decode($json, true);
if (json_last_error() !== JSON_ERROR_NONE) {
throw new RuntimeException('Invalid JSON: ' . json_last_error_msg());
}
if (!is_array($data)) {
throw new UnexpectedValueException('Expected the JSON root to be an array.');
}
Common Mistakes
Only increasing the execution limit
<?php
set_time_limit(600);
while (true) {
// Still never ends.
}
A larger limit hides the symptom temporarily but does not repair an infinite loop. First verify that every loop has a reachable stopping condition.
Forgetting to update a loop counter
<?php
$page = 1;
while ($page <= 10) {
// Fetch page data.
// Missing: $page++
}
Update the counter, or break when the API says there are no more results.
Making an HTTP request for every item
<?php
foreach ($ids as $id) {
$json = file_get_contents("https://api.example.com/items/{$id}");
}
Hundreds of sequential remote requests can easily exceed a request budget. Use a bulk endpoint, pagination, caching, or background processing when available.
Ignoring download failure
Comparisons
| Approach | What it solves | Best use | Limitation |
|---|---|---|---|
| Fix loop condition | Infinite or runaway loops | A counter, cursor, or condition does not advance | Does not make a genuinely slow API faster |
set_time_limit(60) | A legitimate job that needs slightly longer | Controlled scripts with known work | Does not fix bad logic; server policy may restrict it |
| HTTP client timeout | A remote server that responds too slowly | Downloads and API calls | Does not reduce local processing time |
| Batching | Large local processing workloads | Imports and database writes | Requires code to track batches/progress |
| Pagination | Oversized API responses | APIs that expose pages or cursors | Requires API support |
Cheat Sheet
// Read the configured script time limit.
echo ini_get('max_execution_time');
// Request a limit for the current script.
set_time_limit(60);
// Stop waiting on an HTTP stream after 10 seconds.
$context = stream_context_create([
'http' => ['timeout' => 10],
]);
$json = file_get_contents($url, false, $context);
if ($json === false) {
throw new RuntimeException('Download failed');
}
// Decode JSON and throw on malformed content.
$data = json_decode($json, true, 512, JSON_THROW_ON_ERROR);
- The default execution limit is often 30 seconds, but check your active configuration.
- The error line is where execution stopped, not necessarily where the slowdown began.
- Ensure every
whileloop changes data used by its condition. - Set a network timeout for remote requests.
- Validate a download and decoded JSON before iterating.
- Use batches or API pages for large datasets.
FAQ
What does “Maximum execution time of 30 seconds exceeded” mean in PHP?
PHP stopped the script because it ran longer than its configured execution-time limit, commonly 30 seconds.
Does the reported line contain the bug?
Not always. It is the line PHP was executing when the timer expired. The actual delay may be an earlier network request or expensive work repeated in a loop.
How do I increase the PHP execution time limit?
Use set_time_limit(60) for the current script, or change max_execution_time in the active php.ini and restart the server. Fix the cause first.
Why does increasing max_execution_time not fix my script?
It only allows more time. An infinite loop, unavailable API, or unbounded import can still run until the new limit is reached.
How can I prevent a slow JSON download from blocking PHP?
Set an HTTP timeout using a stream context or an HTTP client, check for request failure, and handle the error before decoding JSON.
Should I download all API data in one request?
Usually not when the API supports pagination. Request smaller pages, process each page, and stop when there are no more results.
Is this a memory-limit error?
No. Execution time and memory are separate limits. A memory error typically mentions Allowed memory size exhausted.
Mini Project
Description
Build a small PHP JSON importer that downloads a remote list, validates it, processes records in batches, and reports how long the work took. This mirrors a basic data-import endpoint while keeping network and processing failures visible.
Goal
Safely fetch JSON and process each valid record without relying on an unbounded loop or a single silent failure.
Requirements
Use an HTTP timeout when downloading the JSON.|Stop with a clear error if the download or JSON decoding fails.|Confirm that the decoded JSON is an array before processing it.|Process the records in batches of 100.|Print the number of processed records and elapsed time.
Keep learning
Related questions
Are PDO Prepared Statements Enough to Prevent SQL Injection in PHP?
Learn how PDO prepared statements prevent SQL injection in PHP, what they protect, and the mistakes that still leave MySQL apps vulnerable.
Can You Bind an Array to an IN Clause in PHP PDO?
Learn how PDO handles placeholders in IN() clauses, why arrays cannot be bound directly, and the safe PHP pattern to build dynamic queries.
Choosing the Right MySQL Collation for PHP and UTF-8
Learn how MySQL character sets and collations work with PHP, and how to choose a practical UTF-8 setup for web applications.