InAppWebView Inspector 🔍
A powerful WebView inspector and debugging tool for flutter_inappwebview
. Provides real-time console monitoring, JavaScript execution, and script history management with a draggable overlay interface.
🤖 Developed with Claude: This Flutter library was developed using Vibe coding methodology in collaboration with Claude AI, showcasing the power of AI-assisted development and human-AI collaborative programming.
🌍 Multi-language Documentation
- English | 한국어 (Korean) | 日本語 (Japanese)
✨ Features
🚀 Zero Setup Auto UI Injection (New!)
- No Manual Widget Placement: Inspector UI automatically injects as overlay when
show()
is called - Smart Context Discovery: Automatic BuildContext discovery via WidgetsBinding and NavigatorKey fallback
- Developer-Controlled: User controls when auto-injection is enabled via debug mode initialization
- Hot Reload Compatible: Robust overlay system that works seamlessly with Flutter's hot reload
- Performance Optimized: Optional NavigatorKey integration for instant context access
- Zero Configuration: Just call
toggle()
and the UI appears - no Stack widgets or manual placement needed
🖥️ Real-time Console Monitoring
- Live Console Output: Monitor all JavaScript console messages (
log
,warn
,error
,debug
) in real-time - Color-coded Messages: Different colors for different log levels for easy identification
- Timestamp Display: Each message includes precise timestamp information
- Multi-line Support: Full support for long messages and multi-line output
- Clean Interface: Removed unnecessary labels for streamlined debugging experience
🚀 Enhanced JavaScript Execution
- Interactive Console: Execute JavaScript code directly in your WebView with intelligent result handling
- Smart DOM Object Processing:
document.querySelector("h1")
→ Shows element details (tag, id, class, text content)document.querySelectorAll("p")
→ Lists all matching elements with comprehensive informationdocument.body.classList
→ Automatically converts to readable array format- Functions and complex objects → Displays in developer-friendly format
- Enhanced Error Handling: Comprehensive error messages with helpful suggestions for common DOM operations
- Unicode & Base64 Support: Advanced script encoding options for complex scenarios
📚 Intelligent Script History System
- Pre-loaded Scripts: 15+ commonly used JavaScript snippets ready to use immediately
- Frequency-based Sorting: Most-used scripts automatically appear first
- Memory-based Storage: Fast, lightweight history management without file I/O
- Smart Suggestions: Context-aware script recommendations
- Usage Tracking: Automatically tracks and prioritizes frequently used scripts
🎯 Multi-WebView Management
- Multiple WebView Support: Handle unlimited WebViews in a single application
- Easy Switching: Quick dropdown to switch between registered WebViews
- Individual Monitoring: Each WebView maintains its own console and execution context
- Automatic Registration: Simple API to register and manage WebView instances
🌍 Comprehensive Internationalization
- 8 Languages Supported: English, Korean, Japanese, Spanish, French, German, Chinese (Simplified), Portuguese
- Auto-detection: Automatic language detection from system locale
- Easy Localization: Simple API to set preferred language
- Consistent UI: All interface elements properly localized
🎨 Advanced User Interface
- Draggable Overlay: Move the inspector anywhere on screen with smooth drag interactions
- Resizable Interface: Switch between compact and maximized modes for different use cases
- SafeArea Aware: Automatically adjusts to device screen constraints and notches
- Stack-based Architecture: Stable popup system without overlay conflicts
- Clean Design: Minimal, developer-focused interface optimized for productivity
Installation
Add this to your package's pubspec.yaml
file:
dependencies:
inappwebview_inspector: ^0.2.1
flutter_inappwebview: ^6.1.5
Then run:
$ flutter pub get
🚀 Quick Start
1. Initialize the Inspector
Add this to your main()
function:
import 'package:flutter/foundation.dart';
import 'package:inappwebview_inspector/inappwebview_inspector.dart';
void main() {
// Zero setup initialization - show() will auto-inject UI
if (kDebugMode) {
InAppWebViewInspector.initializeDevelopment(
enableScriptHistory: true,
maxScriptHistoryCount: 25,
localizations: InAppWebViewInspectorLocalizations.english, // Change as needed
onScriptExecuted: (script, webViewId) {
print('Executed: $script on $webViewId');
},
onConsoleLog: (log) {
print('Console [${log.levelText}]: ${log.message}');
},
);
}
runApp(MyApp());
}
2. Add NavigatorKey for Optimal Performance (Recommended)
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'WebView Inspector Demo',
// Add navigatorKey for optimal auto UI injection performance
navigatorKey: InAppWebViewInspector.navigatorKey,
home: MyWebViewPage(),
);
}
}
3. Simple WebView Setup - Zero Manual UI Placement
✨ New: Zero Setup Auto UI Injection - No need to manually add widgets to your UI!
import 'package:flutter/material.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
import 'package:inappwebview_inspector/inappwebview_inspector.dart';
class MyWebViewPage extends StatefulWidget {
@override
_MyWebViewPageState createState() => _MyWebViewPageState();
}
class _MyWebViewPageState extends State<MyWebViewPage> {
InAppWebViewController? webViewController;
final String webViewId = 'main_webview';
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('WebView with Inspector'),
actions: [
// Toggle button - UI will auto-inject when pressed!
IconButton(
icon: Icon(Icons.bug_report),
onPressed: InAppWebViewInspector.toggle,
tooltip: 'Toggle Inspector\n(Zero Setup - UI Auto-Injected!)',
),
],
),
// ✨ No Stack needed! Inspector UI auto-injects as overlay
body: Column(
children: [
// Your main WebView - Inspector UI auto-injects when show() is called
Expanded(
child: InAppWebView(
initialUrlRequest: URLRequest(
url: WebUri('https://flutter.dev'),
),
onWebViewCreated: (controller) {
webViewController = controller;
// Register WebView with inspector
InAppWebViewInspector.registerWebView(
webViewId,
controller,
'https://flutter.dev',
);
},
onLoadStop: (controller, url) {
// Update URL in inspector when navigation occurs
if (url != null) {
InAppWebViewInspector.updateWebViewUrl(
webViewId,
url.toString(),
);
}
},
onConsoleMessage: (controller, consoleMessage) {
// Forward console messages to inspector
InAppWebViewInspector.addConsoleLog(
webViewId,
consoleMessage,
);
},
initialSettings: InAppWebViewSettings(
isInspectable: true, // Enable debugging
javaScriptEnabled: true,
domStorageEnabled: true,
),
),
),
],
),
);
}
@override
void dispose() {
// Clean up when page is disposed
InAppWebViewInspector.unregisterWebView(webViewId);
super.dispose();
}
}
4. Control Inspector Visibility
// Show/hide inspector - UI automatically injects as overlay!
InAppWebViewInspector.show(); // ✨ Auto-injects UI overlay
InAppWebViewInspector.hide(); // Removes overlay
InAppWebViewInspector.toggle(); // ✨ Toggle with auto-injection
// Enable/disable inspector
InAppWebViewInspector.enable();
InAppWebViewInspector.disable();
// Check status
bool isVisible = InAppWebViewInspector.isVisible;
bool isEnabled = InAppWebViewInspector.isEnabled;
⚙️ Configuration Options
Development Mode (Recommended for Debug Builds)
// Zero setup - show() always auto-injects UI
if (kDebugMode) {
InAppWebViewInspector.initializeDevelopment(
enableScriptHistory: true,
maxScriptHistoryCount: 25,
maxConsoleLogCount: 500,
localizations: InAppWebViewInspectorLocalizations.english,
onScriptExecuted: (script, webViewId) {
print('Script executed on $webViewId: $script');
},
onConsoleLog: (log) {
print('Console [${log.levelText}]: ${log.message}');
},
);
}
Production Mode (Minimal Impact)
// Only initialize in production if needed
if (!kReleaseMode) {
InAppWebViewInspector.initializeProduction(
maxConsoleLogCount: 50,
enableAutoResultLogging: false,
enableScriptHistory: false,
localizations: InAppWebViewInspectorLocalizations.english,
);
}
Advanced Custom Configuration
// Advanced configuration with auto UI injection
if (kDebugMode) {
InAppWebViewInspector.initializeWithConfig(
InAppWebViewInspectorConfig(
debugMode: true,
maxConsoleLogCount: 1000,
enableAutoResultLogging: true,
enableUnicodeQuoteNormalization: true,
enableBase64ScriptEncoding: true,
enableScriptHistory: true,
maxScriptHistoryCount: 30,
localizations: InAppWebViewInspectorLocalizations.korean, // Multi-language support
onScriptExecuted: (script, webViewId) {
// Custom script execution callback
analytics.logEvent('script_executed', {'webview_id': webViewId});
},
onConsoleLog: (log) {
// Custom console logging
if (log.level == ConsoleMessageLevel.ERROR) {
crashlytics.recordError(log.message, null);
}
},
onError: (error, webViewId) {
// Error handling callback
print('Inspector error in $webViewId: $error');
},
),
);
}
Language Configuration
// Available localizations
InAppWebViewInspectorLocalizations.english
InAppWebViewInspectorLocalizations.korean
InAppWebViewInspectorLocalizations.japanese
InAppWebViewInspectorLocalizations.spanish
InAppWebViewInspectorLocalizations.french
InAppWebViewInspectorLocalizations.german
InAppWebViewInspectorLocalizations.chineseSimplified
InAppWebViewInspectorLocalizations.portuguese
// Auto-detect from system locale
final localization = InAppWebViewInspectorLocalizations.getByLanguageCode(
Localizations.localeOf(context).languageCode
);
🎯 Advanced Usage Examples
Multiple WebViews Management
class MultiWebViewExample extends StatefulWidget {
@override
_MultiWebViewExampleState createState() => _MultiWebViewExampleState();
}
class _MultiWebViewExampleState extends State<MultiWebViewExample> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Multiple WebViews'),
actions: [
// Single toggle button for all WebViews - UI auto-injects!
IconButton(
icon: Icon(Icons.bug_report),
onPressed: InAppWebViewInspector.toggle,
tooltip: 'Toggle Inspector\n(Zero Setup Auto UI)',
),
],
),
// ✨ No Stack needed! Inspector UI auto-injects as overlay
body: Column(
children: [
// First WebView
Expanded(
child: InAppWebView(
onWebViewCreated: (controller) {
InAppWebViewInspector.registerWebView(
'webview_1',
controller,
'https://flutter.dev',
);
},
onConsoleMessage: (controller, consoleMessage) {
InAppWebViewInspector.addConsoleLog('webview_1', consoleMessage);
},
initialSettings: InAppWebViewSettings(
isInspectable: true,
javaScriptEnabled: true,
),
),
),
// Second WebView
Expanded(
child: InAppWebView(
onWebViewCreated: (controller) {
InAppWebViewInspector.registerWebView(
'webview_2',
controller,
'https://dart.dev',
);
},
onConsoleMessage: (controller, consoleMessage) {
InAppWebViewInspector.addConsoleLog('webview_2', consoleMessage);
},
initialSettings: InAppWebViewSettings(
isInspectable: true,
javaScriptEnabled: true,
),
),
),
],
),
);
}
}
Custom Console Messages
// Add custom messages from Flutter
InAppWebViewInspector.instance.addCustomConsoleLog(
InAppWebViewInspectorConsoleMessage(
webViewId: 'main',
level: ConsoleMessageLevel.WARNING,
message: 'Custom warning from Flutter side',
source: null, // Clean interface without source labels
line: null,
timestamp: DateTime.now(),
),
);
// Add development debug messages
InAppWebViewInspector.instance.addCustomConsoleLog(
InAppWebViewInspectorConsoleMessage(
webViewId: 'main',
level: ConsoleMessageLevel.LOG,
message: 'Flutter lifecycle: App resumed',
source: null,
line: null,
timestamp: DateTime.now(),
),
);
Programmatic Script Execution
// Execute custom scripts programmatically
void executeCustomScripts() {
final inspector = InAppWebViewInspector.instance;
// Simple value retrieval
inspector.executeScript('document.title');
// Complex DOM operations
inspector.executeScript('''
const links = document.querySelectorAll('a');
Array.from(links).map(link => ({
text: link.textContent?.trim(),
href: link.href,
className: link.className
}));
''');
// Error handling example
inspector.executeScript('''
try {
const result = performComplexOperation();
console.log('Operation successful:', result);
return result;
} catch (error) {
console.error('Operation failed:', error.message);
return { error: error.message, stack: error.stack };
}
''');
}
🛠️ Pre-loaded Utility Scripts
The inspector comes with 15+ ready-to-use JavaScript snippets:
Page Information
document.title
- Get current page titlewindow.location.href
- Get current URLdocument.readyState
- Check page load statedocument.getElementsByTagName("*").length
- Count all elements
DOM Manipulation
document.querySelector("selector")
- Find single element with detailsdocument.querySelectorAll("selector")
- Find all matching elementsdocument.body.innerHTML
- Get page HTML contentdocument.cookie
- View all cookies
Browser & Performance
navigator.userAgent
- Get browser informationwindow.innerWidth + "x" + window.innerHeight
- Get viewport sizeperformance.now()
- High-precision timingObject.keys(window)
- List global variables
Storage Access
localStorage.getItem("key")
- Access local storagesessionStorage.getItem("key")
- Access session storage
Development Utilities
console.log("Hello World");
- Basic console logging
📸 Screenshots
iOS Inspector Interface

The inspector running on iOS showing the draggable overlay interface
Android Inspector Interface

The inspector running on Android with the same powerful debugging features
Key Interface Features Shown:
- 🖱️ Draggable Overlay: Move the inspector anywhere on screen
- 📱 Responsive Design: Adapts to different screen sizes and orientations
- 🎯 WebView Selector: Dropdown to switch between multiple WebViews
- ⌨️ Interactive Console: JavaScript input field with history dropdown
- 📋 Real-time Logs: Color-coded console output with timestamps
- 🔄 Resizable Interface: Toggle between compact and maximized modes
🔄 Migration Guide: v0.1.x → v0.2.0
✨ What's New in v0.2.0
Major Feature: Zero Setup Auto UI Injection
- No more manual widget placement required
- Automatic context discovery and overlay injection
- Simplified integration with just
toggle()
calls
🚨 Breaking Changes
1. Widget Placement No Longer Required (Simplified - Not Breaking)
Before (v0.1.x): Manual Stack placement required
// ❌ Old way - Still works but not needed
Scaffold(
body: Stack(
children: [
YourContent(),
const InAppWebViewInspectorWidget(), // Manual placement
],
),
)
After (v0.2.0): Zero setup auto-injection (Recommended)
// ✅ New way - UI auto-injects as overlay
Scaffold(
body: YourContent(), // No Stack needed!
)
// Just call toggle - UI appears automatically
InAppWebViewInspector.toggle();
2. NavigatorKey Integration (New Recommendation)
For optimal performance, add NavigatorKey to your MaterialApp:
// ✅ Recommended for v0.2.0
MaterialApp(
navigatorKey: InAppWebViewInspector.navigatorKey, // New
home: YourHomePage(),
)
📋 Migration Steps
Step 1: Update Dependencies
dependencies:
inappwebview_inspector: ^0.2.1 # Updated
flutter_inappwebview: ^6.1.5
Step 2: Add NavigatorKey (Recommended)
MaterialApp(
navigatorKey: InAppWebViewInspector.navigatorKey, // Add this line
home: YourHomePage(),
)
Step 3: Simplify UI (Optional)
You can now remove manual Stack placement:
// Before: Required Stack
Scaffold(
body: Stack(
children: [
YourContent(),
const InAppWebViewInspectorWidget(),
],
),
)
// After: Simple layout - Inspector auto-injects
Scaffold(
body: YourContent(),
)
Step 4: Test Auto-Injection
// Inspector UI will auto-inject when you call:
InAppWebViewInspector.show();
InAppWebViewInspector.toggle();
⚡ Performance Improvements
- Faster Context Discovery: NavigatorKey provides instant context access
- Reduced Widget Tree: No manual Stack widgets needed
- Hot Reload Friendly: Robust overlay system works seamlessly with Flutter's hot reload
🔧 Troubleshooting Migration Issues
- Inspector not appearing: Add
navigatorKey: InAppWebViewInspector.navigatorKey
to MaterialApp - "No Overlay widget found": Ensure you're calling
toggle()
after initialization - Layout issues: Remove manual Stack placement - auto-injection handles positioning
🆕 New Features in v0.2.0
- Automatic UI Injection: Zero setup overlay system
- Smart Context Discovery: Automatic BuildContext discovery
- NavigatorKey Integration: Optional performance optimization
- Enhanced Error Recovery: Better fallback mechanisms
- Hot Reload Compatibility: Improved development experience
⚠️ Important Implementation Notes
✨ Zero Setup Auto UI Injection
New Simplified Approach: No manual widget placement required!
✅ New Zero Setup Method: Auto UI injection (Recommended)
// 1. Add NavigatorKey for optimal performance
MaterialApp(
navigatorKey: InAppWebViewInspector.navigatorKey, // ✅ Optimal setup
home: MyWebViewPage(),
)
// 2. Simple UI with no Stack needed
Scaffold(
body: Column( // ✅ Simple layout
children: [
Expanded(
child: InAppWebView(
// Register WebView and inspector auto-injects UI
onWebViewCreated: (controller) {
InAppWebViewInspector.registerWebView('main', controller, url);
},
),
),
],
),
)
// 3. Toggle inspector - UI auto-appears as overlay!
InAppWebViewInspector.toggle(); // ✅ Zero manual UI work
Legacy Manual Widget Placement (Still Supported)
For advanced use cases, you can still manually place the widget:
Scaffold(
body: Stack(
children: [
YourMainContent(),
const InAppWebViewInspectorWidget(), // Manual placement
],
),
)
Common Issues & Solutions
- Inspector not appearing: Ensure NavigatorKey is added to MaterialApp for optimal context discovery
- Auto UI injection fails: Check that you're in debug mode and inspector is properly initialized
- "No Overlay widget found": Add
navigatorKey: InAppWebViewInspector.navigatorKey
to your MaterialApp - Dependency conflict with git-sourced flutter_inappwebview: Add dependency override
If your app uses flutter_inappwebview from git source:
dependencies:
inappwebview_inspector: ^0.2.1
flutter_inappwebview:
git:
url: https://github.com/pichillilorenzo/flutter_inappwebview.git
ref: master
path: flutter_inappwebview
dependency_overrides:
flutter_inappwebview:
git:
url: https://github.com/pichillilorenzo/flutter_inappwebview.git
ref: master
path: flutter_inappwebview
Development vs Production
Development Build with Auto UI Injection:
if (kDebugMode) {
InAppWebViewInspector.initializeDevelopment(
enableScriptHistory: true,
maxConsoleLogCount: 500,
);
}
Production Build (Optional):
if (!kReleaseMode) {
InAppWebViewInspector.initializeProduction(
maxConsoleLogCount: 50,
enableScriptHistory: false,
);
}
📱 Example App
The example app demonstrates:
- ✅ Complete WebView integration with inspector
- ✅ Multi-language support demonstration
- ✅ Pre-loaded script usage
- ✅ Enhanced DOM object handling
- ✅ Multiple WebView management
- ✅ Custom script execution examples
Run the example:
cd example && flutter run
📋 Requirements
- Flutter: >= 3.24.0
- Dart: >= 3.5.0
- flutter_inappwebview: >= 6.1.5
🌐 Platform Support
Platform | Status | Notes |
---|---|---|
Android | ✅ Full Support | All features available |
iOS | ✅ Full Support | All features available |
🤝 Contributing
This project demonstrates the power of AI-assisted development using Claude and Vibe coding methodology. Contributions are welcome!
How to Contribute
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature
) - Test your changes thoroughly
- Commit your changes (
git commit -m 'Add amazing feature'
) - Push to the branch (
git push origin feature/amazing-feature
) - Open a Pull Request
Development Setup
# Clone the repository
git clone https://github.com/baccusf/inappwebview_inspector.git
cd inappwebview_inspector
# Install dependencies
flutter pub get
# Run tests
flutter test
# Run example
cd example && flutter run
📄 License
This project is licensed under the MIT License - see the LICENSE file for details.
🙏 Acknowledgments
- 🤖 Claude AI: This library was developed through AI-human collaborative programming using Claude
- ⚡ Vibe Coding: Demonstrated the effectiveness of AI-assisted development methodology
- 💙 Flutter Community: For providing the amazing Flutter framework
- 🌐 flutter_inappwebview: For the excellent WebView foundation
📞 Support & Community
- 🐛 Issues: Report bugs and issues
- 💡 Features: Request new features
- 📖 Documentation: Check the comprehensive CLAUDE.md for development guidance
- 💬 Discussions: Join community discussions
🔗 Related Links
- 📦 pub.dev: Package on pub.dev
- 🌐 Repository: GitHub Repository
- 📚 flutter_inappwebview: Core WebView package
- 🤖 Claude: Learn more about Claude AI
Happy debugging with AI-assisted development! 🐛✨🤖